简单的小重绘

Posted 夜空中最亮的星

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简单的小重绘相关的知识,希望对你有一定的参考价值。

1.当我们改变窗体的大小或者最小化窗体后为什么窗体不消失呢?

原因是画布是在顶级容器中画出来的,而顶级容器(所有的组件)也都是由系统画出来的,窗体组件在改变大小后,原来的窗体就已经不存在了(组件会自动重新绘制,我们自己画的图就会消失),我们看到的窗体是新绘制出来的窗体。

2.怎么解决图形消失的问题呢?

  1.定义图形类,该类用来存储图形的数据。

  2.你每画一个图形,就需要实例化一个图形对象,图形对象就要存储在数组中。

  3.你在哪一个组件上绘制图形,那么就需要重写该组件的重绘(paint)方法,在重绘方法中,将数组中的数据取出,重新再绘制一次。

3.重绘的实现步骤

1.定义一个Shape图形类,定义图形的属性。

2.DrawFrame类中定义一个Shape类型的数组。

3.Shape类型的数组传递到DrawListener事件处理类中。

4.在绘制图形的时候,将图形的数据存入到Shape对象中,然后将Shape对象存入到数组中。

5.DrawFrame类中,重写paint方法,在方法中遍历数组,获取数组中的Shape对象,根据对象的数据绘制图形。

下面是我刚开始写的代码:

package 重绘;

import java.awt.FlowLayout;

import java.awt.Graphics;

import java.awt.Graphics2D;

import javax.swing.JButton;

import javax.swing.JFrame;

/**

 * 定义画图界面类,该类实现JFrame窗体类

 */

public class we extends JFrame {

/**

 *

 */

public static void main(String [] args){

we df = new we();

df.initUI();

}

public void initUI(){

this.setTitle("简单画图");

this.setSize(600, 500);

this.setDefaultCloseOperation(3);

this.setLocationRelativeTo(null);

this.setLayout(new FlowLayout());

JButton butLine = new JButton("直线");

this.add(butLine);

JButton butSharp = new JButton("矩形");

add(butSharp);

JButton butAngle = new JButton("任意多边形");

add(butAngle);

JButton butHair = new JButton("");

add(butHair);

this.setVisible(true);

Graphics g = this.getGraphics();

sd dl = new sd();

this.addMouseListener(dl);

dl.setG(g);

butLine.addActionListener(dl);

butSharp.addActionListener(dl);   

butAngle.addActionListener(dl);

butHair.addActionListener(dl);

//3.Shape类型的数组传递到DrawListener事件处理类中。

dl.setArrayShape(arrayShape);

}

//2.DrawFrame类中定义一个Shape类型的数组。

public Shape[] arrayShape = new Shape[1000]; //注意不能写在public void initUI(){}里面

/**

 * 5.DrawFrame类中,重写paint方法,在方法中遍历数组,获取数组中的Shape对象,根据对象的数据绘制图形。

 */

public void paint(Graphics g){

super.paint(g); //super表示调用父类中的paint方法。

Graphics2D g2d = (Graphics2D)g;

for(int i=0;i<arrayShape.length;i++){

Shape shape = arrayShape[i];  //获取Shape对象

if(null != shape){

g.setColor(shape.color);

g2d.setStroke(shape.stroke);

if(shape.type.equals("直线")){

g.drawLine(shape.x1,shape.y1,shape.x2,shape.y2);

}else if(shape.type.equals("")){

g.drawOval(shape.x1,shape.y1,shape.x2,shape.y2);

}else if(shape.type.equals("矩形")){

g.drawRect(shape.x1,shape.y1.shape.x2,shape.y2);

}

else if(shape.type.equals("任意多边形")){

g.drawLine(shape.x1,shape.y1,shape.x2,shape.y2);

}

}else{

break;

}

}

}

}   //可以改为:

if(shape.type.equals(“直线")||shape.type.equals("任意多边形")){

g.drawLine(shape.x1,shape.y1,shape.x2,shape.y2);

}else if(shape.type.equals("")){

g.drawOval(shape.x1,shape.y1,shape.x2,shape.y2);

}else if(shape.type.equals("矩形")){

g.drawRect(shape.x1,shape.y1.shape.x2,shape.y2);

}

 

 

 

 

 

package 重绘;

import java.awt.BasicStroke;

import java.awt.Color;

import java.awt.Graphics;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.awt.event.MouseEvent;

import java.awt.event.MouseListener;

 

/**

 * 1.新建一个DrawListener事件处理类,该类实现MouseListener鼠标事件接口,实现接口中的抽象方法。

 */

public class sd implements MouseListener,ActionListener{

 

private int x1,y1,x2,y2;//2.定义四个整数属性,用来存储图形的坐标值

private Graphics g ;//定义画笔画布类的对象名

private String type = "直线";

int count;

int ex, ey;

int sx, sy;

int x,y;

 

 

//DrawFrame类借Graphics画笔画布对象的方法

public void setG(Graphics gr){

g = gr;

}

 

private Shape[] arrayShape;  //3.Shape类型的数组传递到DrawListener事件处理类中。

private int index = 0; //3.记录存储的元素个数

// 3.Shape类型的数组传递到DrawListener事件处理类中。

public void setArrayShape(Shape[] arrayShape){

this.arrayShape = arrayShape;

}

 

/**

     * 当你的鼠标在事件源上发生单击动机时执行的方法(按下和释放必须要在同一个位置上)

     */

    public void mouseClicked(MouseEvent e){

     x1 = e.getX();

y1 = e.getY();

x2 = e.getX();

y2 = e.getY();

if (type.equals("")) {

g.drawOval(x1, y1, x2, y2);

Shape shape = new Shape(x1,y1,x2,y2,Color.black,new BasicStroke(1),"",sx,sy,ex,ey,count,x,y);  //改成:Shape shape = new Shape(x1,y1,x2,y2,Color.black,new BasicStroke(1),""

     arrayShape[index++] = shape;

     if(index==1000) index = 0;  //如果已经存入了1000个图形,那么index重置为0

}

if (type.equals("矩形")) {

g.drawRect(x1, y1, x2, y2);Shape shape = new Shape(x1,y1,x2,y2,Color.black,new BasicStroke(1),"矩形",sx,sy,ex,ey,count,x,y);  //改成:Shape shape = new Shape(x1,y1,x2,y2,Color.black,new BasicStroke(1),"矩形"

     arrayShape[index++] = shape;

     if(index==1000) index = 0;//如果已经存入了1000个图形,那么index重置为0

}

 

if (type.equals("任意多边形") && count != 0) {// 判断是否已经画完任意多边形的第一条线了

// 获取点击的坐标值

int x = e.getX();

int y = e.getY();

if (e.getClickCount() == 2) {// 判断是双击,图形要闭合

// 使用x,yexey画闭合的第一条线

g.drawLine(ex, ey, x, y);

g.drawLine(sx, sy, x, y);

count = 0;

Shape shape = new Shape(x,y,sx,sy,Color.black,new BasicStroke(1),"任意多边形",ex,ey,x1,y1,x2,y2,count);  //改成:Shape shape = new Shape(x1,y1,x2,y2,Color.black,new BasicStroke(1),"任意多边形"

 

     arrayShape[index++] = shape;

     if(index==1000) index = 0;  //如果已经存入了1000个图形,那么index重置为0

} else {// 判断不是双击,要画接下来的线

// 根据上一条线的结束点和当前点击的坐标,来绘制直线

g.drawLine(ex, ey, x, y);

Shape shape = new Shape(x,y,ex,ey,Color.black,new BasicStroke(1),"任意多边形",sx,sy,x1,y1,x2,y2,count);  //改成:Shape shape = new Shape(x1,y1,x2,y2,Color.black,new BasicStroke(1),"任意多边形"

     arrayShape[index++] = shape;

     if(index==1000) index = 0;  //如果已经存入了1000个图形,那么index重置为0

// 将当前这条线的结束赋给ex,ey,作为下一条线的起始点

ex = x;

ey = y;

}

}

    

    }

 

    /**

     * 当你的鼠标在事件源上发生按键按下时执行的方法。

     */

    public void mousePressed(MouseEvent e){

     //2.获取按下时的坐标值

     x1 = e.getX();

     y1 = e.getY();

    }

 

    /**

     * 当你的鼠标在事件源上发生按键释放时执行的方法。

     */

    public void mouseReleased(MouseEvent e){

     //2.获取释放时的坐标值

     x2 = e.getX();

     y2 = e.getY();

     if(type.equals("直线")){

     //调用绘制直线的方法

     g.drawLine(x1, y1, x2, y2);

     //4.在绘制图形的时候,将图形的数据存入到Shape对象中,然后将Shape对象存入到数组中。

     Shape shape = new Shape(x1,y1,x2,y2,Color.black,new BasicStroke(1),"直线",sx,sy,ex,ey,count,x,y);   //改成:Shape shape = new Shape(x1,y1,x2,y2,Color.black,new BasicStroke(1),"直线"

     arrayShape[index++] = shape;

     if(index==1000) index = 0;//如果已经存入了1000个图形,那么index重置为0

    

     }

     if (type.equals("任意多边形") && count == 0) {// 判断是否画任意多边形的第一条线

g.drawLine(x1, y1, x2, y2);

Shape shape = new Shape(x1,y1,x2,y2,Color.black,new BasicStroke(1),"任意多边形",sx,sy,ex,ey,count,x,y);

     arrayShape[index++] = shape;

     if(index==1000) index = 0;//如果已经存入了1000个图形,那么index重置为0

// 存储第一条线的起始点

sx = x1;

sy = y1;

// 存储第一条线的结束点

ex = x2;

ey = y2;

count++;// 表示第一条线已经画完了

}

    }

    /**

     * 当你的鼠标进入到事件源时执行的方法。

     */

    public void mouseEntered(MouseEvent e){

    

    }

 

    /**

     * 当你的鼠标离开事件源时执行的方法。

     */

    public void mouseExited(MouseEvent e){

    

    }

    public void actionPerformed(ActionEvent e) {

type = e.getActionCommand();

}

 

}

 

 

package 重绘;

 

import java.awt.BasicStroke;

import java.awt.Color;

import java.awt.Stroke;

 //1.定义一个Shape图形类,定义图形的属性。

public class Shape{  //这种写法在时间复杂度和空间复杂度上市不足的

public int x1, y1, x2, y2,ex,ey,sx,sy;

int count;

int x,y;

public Color color;

public Stroke stroke;

public String type;

   public Shape(){}  //定义Shape对象,后面用于将Shape对象存入到数组中。这一步非常关键,原来就是因为没有写这一句导致画任意多边形的时候定义更多的东西,占用了许多空间.

public Shape(int x1, int y1, int x2, int y2, Color color, Stroke stroke,String type, int ex, int ey, int sx, int sy, int x, int y, int count) {

this.x1 = x1;

this.y1 = y1;

this.x2 = x2;

this.y2 = y2;

    this.ex=ex;

    this.ey=ey;

    this.sx=sx;

    this.sy=sy;

    this.x=x;

    this.y=y;

    this.count=count;

this.color = color;

this.stroke = stroke;

this.type = type;

//这里可以该改成:public Shape(int x1, int y1, int x2,inty2,Color color, Stroke stroke,String type,) {

this.x1 = x1;

this.y1 = y1;

this.x2 = x2;

this.y2 = y2;

      this.color = color;

this.stroke = stroke;

this.type = type;

}

 运行结果:

下面是目前所学的绘制图形的重绘:

/*      1.新建一个DrawListener事件处理类,该类实现MouseListener鼠标事件接口,实现接口中的抽象方法。
  2.定义四个变量,在按下和释放方法中获取按下和释放的坐标值。
  3.定义Grpahics画笔画布类的对象,调用绘制图形的方法来画图。
   我们的组件是画出来的,那么你要在哪一个组件上画图形,那你的画笔画布对象就从这个组件上获取。
  4.实例化DrawListener事件处理类的对象,对象名dl
  5.给事件源窗体对象添加addMouseListener()鼠标监听方法,指定事件处理类对象dl.
 */
package 文雅0604;

import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JButton;
import javax.swing.JFrame;

/**
 * 定义一个画图界面类,该类继承自JFrame窗体类
 */
public class drawJM extends JFrame {
 /**
  *
  */
 private static final long serialVersionUID = 1L;

 /**
  * 程序入口主函数
  */
 public static void main(String[] args) {
  // 实例化窗体类的对象,调用初始化界面的方法
  drawJM df = new drawJM();
  df.initUI();
 }

 // private Shape[] shape = new Shape[100];
 /**
  * 自定义初始化界面的方法
  */
 public void initUI() {
  setTitle("图画");
  setSize(600, 500);
  setDefaultCloseOperation(3);
  setLocationRelativeTo(null);
  setLayout(new FlowLayout());
  JButton butLine = new JButton("直线");
  add(butLine);
  JButton butSharp = new JButton("矩形");
  add(butSharp);
  JButton butAngle = new JButton("任意多边形");
  add(butAngle);
  JButton butHair = new JButton("圆");
  add(butHair);
  JButton b = new JButton("曲线");
  add(b);
  JButton c = new JButton("刷子");
  add(c);
  JButton a = new JButton("橡皮");
  add(a);
  JButton d = new JButton("喷枪");
  add(d);
  JButton f = new JButton("ring");
  add(f);
  JButton h = new JButton("painting");
  add(h);
  JButton i = new JButton("net");
  add(i);
  JButton t = new JButton("tree");
  add(t);
  setVisible(true);
  // 获取窗体上画笔画布对象(注意:必须要在窗体可见之后才能获取画笔画布对象,否则获取的是null)
  Graphics g = getGraphics();
  // 4.实例化DrawListener事件处理类的对象,对象名dl
  drawListener dl = new drawListener();
  // 5.给事件源窗体对象添加addMouseListener()鼠标监听方法,指定事件处理类对象dl.
  addMouseListener(dl);
  addMouseMotionListener(dl);
  // 调用画图Graphics和Shape类
  dl.setGraphics(g);
  //3.将Shape类型的数组传递到DrawListener事件处理类中。
  dl.setArrayShape(arrayShape);
  // 按钮的动作监听,按钮是事件源,也就是说只有当按下按钮才会执行画图的动作,可以参考登录界面的验证登录
  butLine.addActionListener(dl);
  butSharp.addActionListener(dl);
  butAngle.addActionListener(dl);
  butHair.addActionListener(dl);
  b.addActionListener(dl);
  a.addActionListener(dl);
  c.addActionListener(dl);
  d.addActionListener(dl);
  f.addActionListener(dl);
  i.addActionListener(dl);
  h.addActionListener(dl);
  t.addActionListener(dl);

dl.setArrayShape(arrayShape);  //注意:不能遗漏
  
 }
 //2.在DrawFrame类中定义一个Shape类型的数组。
  public Shape[] arrayShape = new Shape[1000];
  
  /**
   *  5.在DrawFrame类中,重写paint方法,在方法中遍历数组,获取数组中的Shape对象,根据对象的数据绘制图形。
   */
  public void paint(Graphics g){
   super.paint(g);//super表示调用父类中的paint方法。
   
   Graphics2D g2d = (Graphics2D)g;
   
   for(int i=0;i<arrayShape.length;i++){
    Shape shape = arrayShape[i];//获取Shape对象
    if(null != shape){
     
     g.setColor(shape.color);
     g2d.setStroke(shape.stroke);
     if(shape.type.equals("直线")||shape.type.equals("任意多边形")||shape.type.equals("ring")||
       shape.type.equals("painting")||shape.type.equals("net")||shape.type.equals("tree")
       ||shape.type.equals("曲线")||shape.type.equals("刷子")||shape.type.equals("橡皮")||
       shape.type.equals("喷枪")){
      g.drawLine(shape.x1, shape.y1, shape.x2, shape.y2);
     }else if(shape.type.equals("圆")){
      g.drawOval(shape.x1,shape. y1, shape.x2, shape.y2);
     }else if(shape.type.equals("矩形")){
      g.drawRect(shape.x1, shape.y1, shape.x2,shape. y2);}
     
    }else{
     break;
    }
   }
  }
}

 

 

package 文雅0604;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
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,
  ActionListener {
 private int x1, y1, x2, y2;// 声明四个整数变量,用来记录按下和释放时的坐标值
 public int sx, sy, ex, ey;// 存储任意多边形的起始点坐标和结束点坐标
 public int count = 0;// 记录画的是任意多边形的第几条线
 public int i = 0;
 public int x3, y3, x4, y4;
 public int t, h;
 public int s;
 public int w = 0;
 public int p = 0;
 public int t1, h1, t2, h2, t3, h3, t4, h4;
 public double a, b, c, d, e, f;
 double x = 0, y = 0;
 double q, v;
 int j;
 double x5, y5;
 private Graphics g;// 声明一个画笔画布类的对象名
 private String type;

 // 向DrawFrame借画笔画布类的对象
 public void setGraphics(Graphics gra) {
  // g = gra;// 把gra传给drawFrame中的g
  g = (Graphics2D) gra;// 强制转型
  // 设置画笔抗锯齿
  ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING,
    RenderingHints.VALUE_ANTIALIAS_ON);
 }

 private Shape[] arrayShape;// 3.将Shape类型的数组传递到DrawListener事件处理类中。
 private int index = 0;// 3.记录存储的元素个数

 // 3.将Shape类型的数组传递到DrawListener事件处理类中。
 public void setArrayShape(Shape[] arrayShape) {
  this.arrayShape = arrayShape;
 }

 /**
  * 当你在事件源上发生鼠标点击动作时执行的方法。(在同一个位置上按下并释放才会执行点击)
  */

 public void mouseClicked(MouseEvent e) {
  x1 = e.getX();
  y1 = e.getY();
  x2 = e.getX();
  y2 = e.getY();
  ((Graphics2D) g).setStroke(new BasicStroke(1));

  if (type.equals("圆")) {
   // 调用绘制圆的方法
   g.drawOval(x1, y1, x2, y2);
   Shape shape = new Shape(x1, y1, x2, y2, Color.black,new BasicStroke(1), "圆");
   arrayShape[index++] = shape;
   if (index == 1000)
    index = 0;// 如果已经存入了1000个图形,那么index重置为0
  }

  if (type.equals("矩形")) {
   g.drawRect(x1, y1, x2, y2);
   Shape shape = new Shape(x1, y1, x2, y2, Color.black,new BasicStroke(1), "矩形");
   arrayShape[index++] = shape;
   if (index == 1000)
    index = 0;// 如果已经存入了1000个图形,那么index重置为0
  }
  if (type.equals("任意多边形") && count != 0) {// 判断是否已经画完任意多边形的第一条线了
             // 获取点击的坐标值

   int x = e.getX();
   int y = e.getY();

   if (e.getClickCount() == 2) {// 判断是双击,图形要闭合
           // 使用x,y和ex,ey画闭合的第一条线
    g.drawLine(ex, ey, x, y);
    Shape shape = new Shape(ex, ey, x, y, Color.black,new BasicStroke(1), "任意多边形");
    arrayShape[index++] = shape;
    if (index == 1000)
     index = 0;// 如果已经存入了1000个图形,那么index重置为0
    g.drawLine(sx, sy, x, y);
    Shape shape1 = new Shape(sx, sy, x, y, Color.black,new BasicStroke(1), "任意多边形");
    arrayShape[index++] = shape1;
    if (index == 1000)
     index = 0;// 如果已经存入了1000个图形,那么index重置为0
    count = 0;
   } else {// 判断不是双击,要画接下来的线
     // 根据上一条线的结束点和当前点击的坐标,来绘制直线
    g.drawLine(ex, ey, x, y);
    Shape shape = new Shape(ex, ey, x, y, Color.black,new BasicStroke(1), "任意多边形");
    arrayShape[index++] = shape;
    if (index == 1000)
     index = 0;// 如果已经存入了1000个图形,那么index重置为0
    // 将当前这条线的结束赋给ex,ey,作为下一条线的起始点
    ex = x;
    ey = y;
   }

  }
  if (type.equals("ring")) {
   double u, f;
   if (e.getClickCount() == 2) {// 双击
    double a = 1.40, b = 1.56, c = 1.40, d = -6.56;
    for (int i = 0; i < 100000; i++) {

     u = d * Math.sin(a * x) - Math.sin(b * y);
     f = c * Math.cos(a * x) + Math.cos(b * y);

     int m = (int) (u * 20 + 300);以上是关于简单的小重绘的主要内容,如果未能解决你的问题,请参考以下文章

鼠标绘制简单图形

除非鼠标移动,否则 Java 物理循环(按间隔重绘)不稳定

回流和重绘

vue基本知识点

使用 tkinter 的简单动画

小部件不会更新/重绘