`
海王子1994
  • 浏览: 43674 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

画板的重绘

 
阅读更多
 

     当我们写好一个简易画板,然后在上面画线,画圆等,再把窗口最小化,接着打开,你发现了什么??对,很神奇的事发生了,不是在做梦,之前的所有图形全部消失了,why??原来, 当窗体在屏幕上显示时,首先是将窗体对象的数据从内存中取出来放到缓存中,再在屏幕上进行绘制。当窗体发生改变的时候,程序会重新从内存中获取更新后的数据绘制。all effort are in vain!那怎么办呢?嗯嗯,方法当然是有的啦,就是重绘!!

     通过重写JFrame类的paint(Graphics g)方法来保存我们画过的形状,大概就是下面这么个过程:

1)创建保存形状的队列(采用泛型)

2)每绘制一个形状,就将绘制过的形状保存到队列。

这里就要提到图形类,其实就是创建一个图形的类,里面有画这个图形的方法啦。不过在此前,要创建一个抽象的Shape类,让图形类去继承它;因为要创建很多图形类嘛,哈哈。

 

之后呢要在事件源上的g(Graphics类)进行重写paint()方法,把队列中存储的图形全部绘制出来,这样就搞定啦。不过要提醒的是,如果是在窗体上进行重写paint()方法,图形可能会越界到其他面板上哦!!

 

大概的代码如下:

 

首先是实现类:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Draw {

	/**
	 * @param args
	 */
	
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//实例化一个画板对象
       Draw sd=new Draw();
       //调用显示画板的方法
       sd.showUI();
	}
    public void showUI()
    {
    	/*
    	 * 实例化一个窗体对象
    	 */
    	JFrame jf=new JFrame();
    	jf.setTitle("普通画板");//设置窗体标题
    	jf.setSize(600,500);//设置窗体大小
    	jf.setLayout(new BorderLayout());//设置窗体布局为边框布局
    	jf.setResizable(false);//禁止窗体改变大小
    	jf.setLocationRelativeTo(null);//设置窗体居中
    	jf.setDefaultCloseOperation(3);//设置关闭窗体关闭程序
    	
    
    	
    	//调用创建北边面板方法
    	JPanel northpanel=creatNorthPanel();
    	//将面板添加到窗体上
    	jf.add(northpanel,BorderLayout.NORTH);
    	
    	//调用创建中间面板方法
    	JPanel centerpanel=creatCenterPanel();
    	//将面板添加到窗体上
    	jf.add(centerpanel,BorderLayout.CENTER);
    	
        	
    	jf.setVisible(true);//设置窗体为可见     //  先让窗体可见,再弄下面的程序!!!!!!!!!!!!!!!!!!!!!!!!
    	
    	Graphics g=centerpanel.getGraphics();//从中间面板中接收Graphics对象
    	
    	DrawListener ml=new DrawListener(g,this);//实例化一个DrawListener类对象
    	//给中间面板添加动作监听器,绑定MouseListener事情处理类对象
        centerpanel.addMouseListener(ml);
        //给中间面板添加动作监听器,绑定MouseMotionListener事件处理类对象
        centerpanel.addMouseMotionListener(ml);

    	
    }
    
    private String str="Line";//定义一个存储图像的属性值
  /*
   * 获得存储图像的属性
   */
	public String getStr()
	{
		return str;
	}
    private Color color;//定义颜色的属性值
    /*
     * 获得颜色的属性
     */
    public Color getColor()
    {
    	return color;
    }
    /*
     *  创建北边面板的方法
     */
    public JPanel creatNorthPanel()
    {   JPanel north_panel=new JPanel();//实例化北边面板的对象
        //设置北边面板的属性
        north_panel.setPreferredSize(new Dimension(500,100));//设置北边面板大小
        north_panel.setLayout(new FlowLayout(FlowLayout.LEFT));//设置北边面板布局为流式布局,并向左对齐
        
        //匿名,实现ActionListener接口
        ActionListener al=new ActionListener()
        {
        	//事情发生类方法
        	public void actionPerformed(ActionEvent e)
        	{   
        		//判断是否点击到"Color"按钮
        		if(e.getActionCommand().equals("Color"))
        		{  //弹出一个颜色选择器,供选择颜色;选择好的颜色返回color
        			color=JColorChooser.showDialog(null, "颜色选择器", Color.BLACK);
        		}
        		else 
        			{//获取按钮上的文本
        			str=e.getActionCommand();//将获得的字符赋给字符串str
            		
        			}
        	}
        };//注意加“;”!!!!!!!!!!!!!!!!!!
       
        
       //创建一位数组,储存按钮上的文本
        String []array={"Line","Rectangle","Oval","RoundRect","Polygon","Pencil","Color","Eraser","Brush","Gunjet"};
       
      // 遍历数组,创建按钮,并添加文本在按钮上
       
        for(int i=0;i<array.length;i++)
        {    
        	JButton jb=new JButton(array[i]);//实例化按钮对象
        	jb.setPreferredSize(new Dimension(100,40));//设置按钮大小
        	//给事件源添加动作监听器方法,绑定事件处理类对象
        	jb.addActionListener(al);
        	north_panel.add(jb);//将按钮添加到北边面板上
        }
    	return north_panel;
    }
    /*
     * 创建中间面板的方法
     */
    public JPanel creatCenterPanel()
    {  JPanel center_panel=new JPanel(){
    	//重写paint()方法
    	public void paint(Graphics g)
    	{
    		super.paint(g);//调用父类的paint()方法
    		//绘制存储的图形
    		for(int i=0;i<DrawListener.list.size();i++)
    		{
    			Shape shape=DrawListener.list.get(i);//获取存储图像类
    			shape.draw(g);//调用图形类绘制方法
    		}
    	}
    };//实例化中间面板的对象
        center_panel.setBackground(Color.WHITE);//设置面板的背景色
            return center_panel;
    }
	
}

 然后是数组队列的创建:

 

import java.util.Collection;


public interface SelfArrayList <E>{

	public void add(E e);//向队列尾部添加元素方法
	public boolean remove(E e);//移除此列表中首次出现的指定元素(如果存在)
	public E get(int index);//取得队列中指定位置的一个对象
	public int size();//得到队列长度	
 	public void add(int index, E e); //将指定的元素插入此列表中的指定位置。 
 	public boolean addAll(Collection<? extends E> c);//按照指定 collection 的迭代器所返回的元素顺序,将该 collection 中的所有元素添加到此列表的尾部。 
	public void clear();// 移除此列表中的所有元素 
 	public 	int indexOf(E e);//返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,则返回 -1。 
 	public boolean isEmpty();//如果此列表中没有元素,则返回 true 
 	public int lastIndexOf(E e);//返回此列表中最后一次出现的指定元素的索引,或如果此列表不包含索引,则返回 -1。 	
 	public E set(int index, E e);// 用指定的元素替代此列表中指定位置上的元素。 
 	public E remove(int index);//移除此列表中指定位置上的元素。 
	
}  

然后是Shape的抽象类:

import java.awt.Color;
import java.awt.Graphics;

public abstract class Shape {

	private int x1,x2,y1,y2;//定义坐标属性
	private Color color;//定义颜色属性
	private int width;//定义宽度属性
	private int height;//定义高度属性
	//构造方法
	public Shape(int x1,int x2,int y1,int y2,Color color,int width,int height)
	{
		this.x1=x1;
		this.x2=x2;
		this.y1=y1;
		this.y2=y2;
		this.color=color;
		this.width=width;
	}
	
	public void draw(Graphics g)
	{
		
	}
	
	public void setx1(int x1)
	{
		this.x1=x1;
	}
     public int getx1()
     {
    	 return x1;
     }
     public void setx2(int x2)
 	{
 		this.x2=x2;
 	}
      public int getx2()
      {
     	 return x2;
      }
      public void sety1(int y1)
  	{
  		this.y1=y1;
  	}
       public int gety1()
       {
      	 return y1;
       }
       public void sety2(int y2)
   	{
   		this.y2=y2;
   	}
        public int gety2()
        {
       	 return y2;
        }
        public void setColor(Color color)
    	{
    		this.color=color;
    	}
         public Color getColor()
         {
        	 return color;
         }
         public void setWidth(int width)
         {
        	 this.width=width;
         }
         public int getWidth()
         {
        	 return width;
         }
         public void setHeight(int height)
         {
        	 this.height=height;
         }
         public int getHeight()
         {
        	 return height;
         }
}

 然后是各种图形类,这里就只放一个直线类和橡皮擦类啦:

 

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
/*
 * 直线的图形类
 */
public class ShapeLine extends Shape {

	//继承的子类要和父类有同一套构造方法
	public ShapeLine(int x1, int x2, int y1, int y2, Color color, int width) {
		super(x1, x2, y1, y2, color, width, width);
		// TODO Auto-generated constructor stub
	}

	//画直线的方法
	public void draw(Graphics g)
	{
		g.setColor(this.getColor());//设置图形颜色
		Graphics2D g2=(Graphics2D)g;//强制转型,把Graphics类型转换成Graphics2D类型
		g2.setStroke(new BasicStroke(this.getWidth()));//设置线条粗细
		g2.drawLine(getx1(), gety1(), getx2(), gety2());//画直线
	}
}

 

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;

public class ShapeEraser extends Shape {

	public ShapeEraser(int x1, int x2, int y1, int y2, Color color, int width,
			int height) {
		super(x1, x2, y1, y2, color, width, height);
		// TODO Auto-generated constructor stub
	}

	public void draw(Graphics g)
	{
		g.setColor(this.getColor());//设置白色颜色
		Graphics2D g2=(Graphics2D)g;//强制转型
		//设置笔的粗细为2.0F,线条端点是CAP_ROUND,点划线模式为 JOIN_ROUND  
	       g2.setStroke(new   BasicStroke(10.0F,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));   
	 	   g2.drawLine(getx1(),gety1(),getx2(),gety2());   
	       g2.setStroke(new   BasicStroke()); 
		
	}
}

 最后是事件监听器:

 

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.Random;

public class DrawListener implements MouseListener ,MouseMotionListener {
	private int x1,x2,y1,y2;//记录鼠标两次点击的坐标
    private Graphics g;//从界面对象上得到的画布对象
    private Graphics2D gg; 
    private Draw sd;
    private int flag=1;
    public int m,n;
    public int x3,y3,x4,y4;
    private int m1=0,n1=0;
    //创建一个数组队列,存储图像类
   public static UseArrayList<Shape> list=new UseArrayList<Shape>();
    
    
    //构造方法,用来接收Graphics对象和Draw类对象
    public DrawListener(Graphics g,Draw sd){
    	this.g=g;
    	this.sd=sd;
    }
    //鼠标按下的点的坐标
    public void mousePressed(MouseEvent e){
    	//记录第一次点击的x,y:通过事件对象e得到的
    	x1=e.getX();
    	y1=e.getY();
    	
    	//获得点击“Polygon”时初次点击的点的坐标
    	if(sd.getStr().equals("Polygon"))
    	{
          x3=e.getX();
          y3=e.getY();
         flag++;
    	if(flag==2)
    	{
    		m=x3;
    		n=y3;
    		x4=m;
	        y4=n;	
    	}
        }
    	
    	//判断鼠标是按左键还是右键
    	if(e.getButton()==1)
    	{  //按左键,颜色为sd得到的黑色
    		g.setColor(sd.getColor());
    	}
    	else if(e.getButton()==3)
    	{ //按右键,颜色为绿色
    		g.setColor(Color.GREEN);
    	}

    }
    //鼠标释放时的坐标
    public void mouseReleased(MouseEvent e)
    {
    	//记录第二次点击时的坐标
    	x2=e.getX();
    	y2=e.getY();
    	
    	//判断是否为Line
    	if(sd.getStr().equals("Line"))
    	{

//    	//调用画布对象的方法,画直线
//    	g.drawLine(x1,y1,x2,y2);
    		
    		Shape shapeLine=new ShapeLine(x1,x2,y1,y2,Color.BLACK,1);
    		shapeLine.draw(g);
    		list.add(shapeLine);//将直线类添加到队列上
    	 
          	
    	}
    	/*
    	 * 判断是否为矩形Rectangle
    	 */
    	if(sd.getStr().equals("Rectangle"))
    	{
//    		g.drawRect(Math.min(x1, x2), Math.min(y1, y2),Math.abs(x1-x2), Math.abs(y1-y2));//Math.min(x1, x2), Math.min(y1, y2)!
    		
    		Shape shapeRectangle=new ShapeRectangle(x1,x2,y1,y2,Color.BLACK,1,4);
    		shapeRectangle.draw(g);
    		list.add(shapeRectangle);//将矩形类添加到队列上
    	}
    	/*
    	 * 判断是否为椭圆形Oval
    	 */
    	if(sd.getStr().equals("Oval"))
    	{
//    		g.drawOval(x1, y1,Math.abs(x1-x2) , Math.abs(y1-y2));
    		Shape shapeOval=new ShapeOval(x1,x2,y1,y2,Color.BLACK,1,4);
    		shapeOval.draw(g);
    		list.add(shapeOval);//将椭圆类添加到队列上
    		
    		
    		
    	}
    	/*
    	 * 判断是否为RoundRect
    	 */
    	if(sd.getStr().equals("RoundRect"))
    	{
//    		g.drawRoundRect(x1, y1, Math.abs(x1-x2),Math.abs(y1-y2), Math.abs(x1-x2)/2,Math.abs(y1-y2)/2 );
    		Shape shapeRoundRect=new ShapeRoundRect(x1,x2,y1,y2,Color.BLACK,1,4);
    		shapeRoundRect.draw(g);
    		list.add(shapeRoundRect);
    		
    	}
    	
    	/*
    	 * 判断是否为Polygon
    	 */
    	//获取拖动过程中的坐标值
		int x = e.getX();
		int y = e.getY();
		
	
		
		
    	if(sd.getStr().equals("Polygon"))
    	{	
    		//判断鼠标点击的坐标是不是与第一次点击的一样,不同则画线
    		if((x!=m)||(y!=n))
    		{    		
    			
//    			//画线
//    			g.drawLine(x4, y4, x, y);
    			Shape shapePolygon=new ShapePolygon(x4,x,y4,y,Color.BLACK,1,4);
        		shapePolygon.draw(g);
        		list.add(shapePolygon);
    			
    			//赋值
    			x4=x;
    			y4=y;
    			
    		}
    		
//    		Shape shapePolygon=new ShapePolygon(x4,y4,x,y,Color.BLACK,1,4);
//    		shapePolygon.draw(g);
//    		list.add(shapePolygon);
    	
    	   
    	}
    }
    /*
     * 当鼠标在事件源上单击时按键执行的方法
     */
    public void mouseClicked(MouseEvent e)
    {   
		
    	if(sd.getStr().equals("Polygon"))
    	{	
    		//获取点击过程中的坐标值
    		int x = e.getX();
    		int y = e.getY();
    	     
    	//如果双击鼠标,当前的点会与初始点连线	
    	    if(x==m1&&y==n1)
    	    {
//    	    	g.drawLine(x, y, m, n);
    	    	Shape shapePolygon=new ShapePolygon(x,m,y,n,Color.BLACK,1,4);
        		shapePolygon.draw(g);
        		list.add(shapePolygon);	
    	    	
    	    	
    	    	flag=1;//使flag归为1,便能改变再次画多边形时的第一次单击的坐标值
    	    }
    	    
    	    m1=e.getX();
    	    n1=e.getY();
    	  	
    	}
    	
    	
    	
    }
    public void mouseEntered(MouseEvent e)
    {}
    public void mouseExited(MouseEvent e)
    {}
	/*
	 * 当鼠标在事件源上拖拉时按键执行的方法
	 */
	public void mouseDragged(MouseEvent e) {
		//判断点击的按钮是否为"Pencil"
		if(sd.getStr().equals("Pencil"))
		{
			//获取x,y的坐标值
			int x=e.getX();
			int y=e.getY();
//			//画线
//			g.drawLine(x1, y1, x, y);
			
	Shape shapePencil=new ShapePencil(x1,x,y1,y, Color.BLACK, 1, 4);
	shapePencil.draw(g);
	list.add(shapePencil);
			
			//赋值
			x1=x;
			y1=y;
			
		}
	///////////////////////////////////////////////////////////////////////////////////////////////////////	
		//判读点击的按钮是否为"Eraser"
		if(sd.getStr().equals("Eraser"))
		{
			//获取x,y的坐标值
			int x=e.getX();
			int y=e.getY();
//			//设置线条为白色
//		   g.setColor(Color.WHITE);
//			//画线
//		   gg =(Graphics2D)g; //实例化一个Graphics2D对象
//		   //设置笔的粗细为2.0F,线条端点是CAP_ROUND,点划线模式为 JOIN_ROUND  
//	       gg.setStroke(new   BasicStroke(10.0F,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));   
//	 	   gg.drawLine(x1,y1,x,y);   
//	       gg.setStroke(new   BasicStroke());  
			
			Shape shapeEraser=new ShapeEraser(x1,x,y1,y,Color.WHITE,1,4);
			shapeEraser.draw(g);
			list.add(shapeEraser);
			
			
			//赋值
			x1=x;
			y1=y;
			
		}
		///////////////////////////////////////////////////////////////////////////////////////////////////////
		//判读点击的按钮是否为"Brush"
				if(sd.getStr().equals("Brush"))
				{
					//获取x,y的坐标值
					int x=e.getX();
					int y=e.getY();
//					//设置线条为选择的颜色
//					   g.setColor(sd.getColor());
//					//画线
//				   gg =(Graphics2D)g; //实例化一个Graphics2D对象
//				   //设置笔的粗细为2.0F,线条端点是CAP_ROUND,点划线模式为 JOIN_ROUND  
//			       gg.setStroke(new   BasicStroke(10.0F,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));   
//			 	   gg.drawLine(x1,y1,x,y);   
//			       gg.setStroke(new   BasicStroke());   
					
					Shape shapeBrush=new ShapeBrush(x1,x,y1,y,Color.BLACK,1,4);
					shapeBrush.draw(g);
					list.add(shapeBrush);
					
					//赋值
					x1=x;
					y1=y;
		////////////////////////////////////////////////////////////////////////////////////////////			
				}
				//判读点击的按钮是否为"Gunjet"
				if(sd.getStr().equals("Gunjet"))
				{
					//获取x,y的坐标值
					int x=e.getX();
					int y=e.getY();
					int x0=0;
					int y0=0;
//					//设置线条为黑色
//					   g.setColor(sd.getColor());
//					//噴槍大小
//					int size=8;
//					//噴槍点數
//					int count=10;
//					for(int i=0;i<count;i++)
//					{  	x0 = new Random().nextInt(size)+ 1;
//						y0 = new Random().nextInt(size) + 1;
//						 g.fillRect(x+x0, y+y0,5,5);
//					}
					
					Shape shapeGunjet=new ShapeGunjet(x1,x,y1,y,Color.BLACK,1,4);
					shapeGunjet.draw(g);
					list.add(shapeGunjet);
				}
				
				
	}
	/*
	 * 事件源上移动鼠标的方法
	 */
	public void mouseMoved(MouseEvent e) {
		
		
	}
    
    
}

 这样就基本完成啦,然后至于对界面的美好等就需要继续努力咯!!

 

分享到:
评论

相关推荐

    易语言画板自绘

    易语言画板自绘源码,画板自绘,标尺子程序_绘制标尺刻度,恢复鼠标状态,无拖动时激活恢复,刻度区重绘,客户区重绘,二级缓冲绘制,客户区刷新,选中辅助线,高亮辅助线,拖动辅助线,客户绘制的图形,GetProp,SetRect,SetProp,...

    易语言画板自绘列表框

    易语言画板自绘列表框源码,画板自绘列表框,重画列表,取现行选中项,加入表项,取现行选中项备注

    易语言画板自绘列表

    易语言画板自绘列表源码,画板自绘列表,重画,挂接,置行高,进度,取表项数,插入项目,更新进度,取选中项,删除表项,取项名称,取项软件大小

    MFC实现高仿画板、绘图软件功能(带详细注释)

    在VS2015环境下,利用MFC框架实现的一款高仿“画图”工具,实现绝大部分功能甚至更多创新点。(注释超详细) 实现了点、直线、曲线、折线、矩形、圆形、多边形等等形状,并且具有区域限制、鼠标捕捉等功能;...

    安卓手绘图片处理画板相关-可以自由画线设置线宽绘画图片图片可以移动旋转放大缩小。添加新图片保留原图片自由选择某个图片的操作可以撤销重绘添加背景编写文字描述.rar

    可以自由画线,设置线宽,绘画...添加新图片、保留原图片、自由选择某个图片的操作、可以撤销、重绘、添加背景、编写文字描述.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。

    java写的画板

    (6)新建文件功能:新建文件,将画板上绘制的内容清空(清空之前可以确认是否需要进行保存)清屏(重绘)功能依次方法; (7)文件保存格式为BMP格式; (8)文字功能:读取文本框中的文本并打印到屏幕鼠标的相应的响应...

    Android studio 画画板程序app毕业设计基于java的画板应用画删改色运行封面(包含源代码+设计报告+运行视频)

    将其画板位图进行重绘,清空画布。4.撤销模块。保存其画笔路径,撤销时删除上一步操作,调用重绘来实现。5.保存绘图模块。先在本地的文件夹上创建一个文件 默认创建的是/sdcard/Pictures/由于文件的名字是不能重复的...

    画板涂鸦demo

    一个模仿了画板涂鸦的小demo.基本的重绘实现了.实现了颜色的变化和笔记粗细的变化

    OpenGL ES之手写绘画板.zip

    OpenGL ES之手写绘画板:详细的实现了PaintView的画笔的颜色、尺寸、笔触等设定切换,并运用OpenGL ES自定义着色器实现画板曲线的绘制,并实现了重做、重绘、橡皮擦、撤销、清除等逻辑的实现。

    java创意画板全功能.zip

    包含图像重绘,迭代图像,递归图形等全功能的创意画板

    易语言自绘画板编辑框

    易语言自绘画板编辑框源码,自绘画板编辑框,编辑_加入高亮文本,系统_光标绘画,系统_修改光标闪烁速度,系统_取文本高宽,初始化文本行数据,系统_窗口回调,数据_文本行数据重置,系统_值当前段,系统_重画文本,取高16位,...

    Java课程设计-JavaSwing实现GUI画板课程设计源码

    1. 实现编写的一个重绘接口。 2. 在用户界面 GUI 类中,继承 JFrame 类. 3. 在事件监听 DrawListener 类中实现了 MouseListener、MouseMotionListener、 ActionListener 监听接口,并重写其绘图方法。 4.在事件监听...

    MFC进度条颜色渐变,中间显示百分比

    本例 1.有对edit重绘,实现画板的功能 2.进度条重绘 比网上流传的老外写的效率高,由于设置背景模式为透明,产生的百分比会模糊,网上那个效率比较的低,一直在重绘,还好是c++速度快

    GDI+自绘一个按钮(像自绘模块的写法,非画板)-易语言

    大概思路1.申请空间存放组件xx,使用__set(),__get(),__quary(),__add(),__del()等汇编操作提高...3.需要重画的组件才重画,提高效率 4.用常量来标识各类状态,方便修改 (e比较蛋.疼的地方,就是没有鼠标移入移出事件...)

    win32完成画图小程序

    win32实现画图小程序,主要功能:画直线、矩形、椭圆,曲线,画板清除,重绘,颜色选择,工具选择,调色板和工具栏的隐藏和显示,调色板的停靠,文件保存和打开

    易语言迷你工具箱

    易语言迷你工具箱源码,迷你工具箱,绘_画板_移动鼠标,绘_取索引,绘_画项目,绘_画热点,绘_画焦点,绘_重画,绘_重画项目,绘_画板_按下左键,绘_文本写出位置,创建事件同步对象,打开事件同步对象

    易语言迷你工具箱2.21

    易语言迷你工具箱2.21源码,迷你工具箱2.21,绘_画板_移动鼠标,绘_取索引,绘_画项目,绘_全部重画,绘_重画项目,绘_画板_按下左键,绘_文本位置,创建事件同步对象,打开事件同步对象

    SPCanvas-master.zip

    使用UIBezierPath 简单实现的画板,实现了后退,前进,橡皮擦,清空画布,保存到系统...整体绘制导致CPU占用过高,这边采用了局部重绘。 通过中点绘制贝塞尔二阶曲线,优化拐角锯齿问题(通过快速打对勾即可看出效果)

Global site tag (gtag.js) - Google Analytics