Swing 4方块绘制删除与多按钮监听

Posted 千秋邈矣独留我

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swing 4方块绘制删除与多按钮监听相关的知识,希望对你有一定的参考价值。

  其实这个问题酝酿好久了。不过一直找不到删除方块的正确姿势。这不,昨晚好不容易找到一个

通过双按钮注册同个接口来实现的方法。下午又折腾了好久,才算解决这个问题。

  参考: http://blog.csdn.net/meditator_hkx/article/details/50734158

  

  先来说说之前一直没有解决的问题。当我们通过下列代码产生一只小可爱时(我吐),表面上一切

正常。然而当我们移动它时

    版本一 : 拉动窗口, 图像大小就会改变, 是我给你的自由过了火

 1 package demo;                                                                    // 导入包名
 2 
 3 import javax.swing.*;
 4 import java.awt.*;
 5 import java.awt.event.*;
 6 
 7 public class Test extends JPanel {
 8     public static void main(String[] args) {
 9         new Test();                                         // 创建Test对象, 实际是调用构造函数
10     }
11     
12     Test() {                                          // 构造函数在类实例化时(使用new方法)被调用           
13         JFrame frame = new JFrame();                                  // (对象是类的实体/实例)
14         
15         frame.getContentPane().add(this);                             // 添加JPanel及其组件
16         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 设置关闭窗口时退出javaw.exe进程
17         frame.setSize(600, 500);                            // 窗口大小设为宽800像素, 高600像素
18         frame.setVisible(true);                   
19     }
20     
21     public void paintComponent(Graphics g) {          // paintComponent()是程序自己会执行的方法
22         int red = (int)(Math.random() * 255);
23         int green = (int)(Math.random() * 255);
24         int blue = (int)(Math.random() * 255);
25         
26         Color randColor = new Color(red, green, blue);  // 红绿蓝是三原色, 由它们混合产生其它颜色
27         g.setColor(Color.pink);
28         g.fillOval(0, 0, this.getWidth(), this.getHeight());  // this.getWidth()是获取窗口的宽
29                               
30         g.setColor(randColor);                                
31         g.fillOval(200, 150, 50, 50);               // 设置椭圆, 参数依旧是左上角x值、y值、宽、高
32         g.setColor(randColor);
33         g.fillOval(400, 150, 50, 50);
34     }
35 }
版本1

  噢耶,前线发来贺电,目前一切正常。可是当我们拉动界面边框时。奇迹出现了。哦不,应该是说

Bug出现了。请看大屏幕。小心亮瞎你的钛合金眼。

   出乎意料的,界面拉长后,小可爱的眼睛变色了。于是我们猜测, 当拉伸窗口时,系

统自动执行的paintComponent()函数又被执行了一次。怎么办呢?天知道。这个时候

起了一直默默无闻的布尔型变量。没错,它就是被拿来控制if语句执行与否的

      版本二: 拉动窗口图像丢失, PS: 记得重画

 1 // 这个不是完整的程序, 只是为了显示和第一版有区别的代码
 2 
 3 public class Test extends JPanel {
 4     boolean isMoved;
 5     
 6     public void paintComponent(Graphics g) {         // paintComponent()是程序自己会执行的方法
 7         if (isMoved) {
 8             int red = (int)(Math.random() * 255);
 9             int green = (int)(Math.random() * 255);
10             int blue = (int)(Math.random() * 255);
11             
12             Color randColor = new Color(red, green, blue);  // 红绿蓝是三原色, 由它们混合产生其它颜色
13             g.setColor(Color.pink);
14             g.fillOval(0, 0, this.getWidth(), this.getHeight()); // this.getWidth()是获取窗口的宽
15                                   
16             g.setColor(randColor);                                
17             g.fillOval(200, 150, 50, 50);               // 设置椭圆, 参数依旧是左上角x值、y值、宽、高
18             g.setColor(randColor);
19             g.fillOval(400, 150, 50, 50);
20             isMoved = false;
21         }
22     }
23 }

  这个版本只是把控制paintComponent()函数执行的布尔变量设为实例变量, 然后在执行

过一次函数之后, 也就是界面打开之后。当我们再次拉动窗口时,会发现,这回连图形都没有了。

哎我的妈呀, 这又是怎么回事呢?原来呀,当我们再次拉动窗口时,画图函数依然会被执行,只

不过是isMove被设为了false,所以程序无法重画,所以界面上当然什么图形都没有啦。

  改进的方法是添加一个else语句, 再重复一遍画图的代码。这样,即使是isMove

变为false, 函数仍然能重画!

     版本三: 加个else, 如果拉动(出现空白), 就多画一次

 1 package demo;                                                  // 导入包名
 2 
 3 import javax.swing.*;
 4 import java.util.*;
 5 import java.awt.*;
 6 import java.awt.event.*;
 7 
 8 public class Test extends JPanel {
 9     boolean isMove = true;                                    // 添加控制画图函数执行的布尔变量
10     Color randColor;
11     public static void main(String[] args) {
12         new Test();                                          // 创建Test对象, 实际是调用构造函数
13     }
14     
15     Test() {                                            // 构造函数在类实例化时(使用new方法)被调用           
16         JFrame frame = new JFrame("猜猜我是谁");                         // (对象是类的实体/实例)
17         
18         frame.getContentPane().add(BorderLayout.CENTER, this);
19         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置关闭窗口时退出javaw.exe进程
20         frame.setSize(600, 500);                             // 窗口大小设为宽800像素, 高600像素
21         frame.setVisible(true);                   
22     }
23     
24     public void paintComponent(Graphics g) {           // paintComponent()是电脑自己会执行的方法
25         if (isMove) {
26             int red = (int)(Math.random() * 255);
27             int green = (int)(Math.random() * 255);
28             int blue = (int)(Math.random() * 255);
29         
30             randColor = new Color(red, green, blue);     // 红绿蓝是三原色, 由它们混合产生其它颜色
31         
32             g.setColor(Color.pink);
33             g.fillOval(0, 0, this.getWidth(), this.getHeight());
34             g.setColor(randColor);                                
35             g.fillOval(200, 150, 50, 50);                  // 设置椭圆, 参数依旧是左上角坐标和长宽
36             g.setColor(randColor);
37             g.fillOval(400, 150, 50, 50);
38             isMove = false;                               // 执行一次画图函数后, isMove变为false 
39         }
40         else {
41             g.setColor(Color.pink);
42             g.fillOval(0, 0, this.getWidth(), this.getHeight());         
43             g.setColor(randColor);                                
44             g.fillOval(200, 150, 50, 50);                         
45             g.setColor(randColor);
46             g.fillOval(400, 150, 50, 50);
47         }
48         
49     }
50 }
最终版本

  由于空间和时间有限, 就不详细介绍主角了。直接贴上代码。大家自个研究下哈。

主要是利用了多个ArrayList数组分别保存了方块的坐标, 尺寸和颜色。然后在返回/

撤销,清屏时分别迭代或者删除。

  至于布局,就是把三个按钮都设置在同一个面板上。最后把面板放在了构架的南区。

 

--------------------------------------------------------------------------------------------------------

  1 package demo;
  2 
  3 import javax.swing.*;
  4 import java.awt.*;
  5 import java.awt.event.*;
  6 import java.util.*;
  7 
  8 public class Test extends JPanel {
  9     boolean isDraw, isBack, isClear;
 10     int listLength, endIndex;
 11     JFrame frame;
 12     ArrayList<Color> colorList = new ArrayList<Color>();
 13     ArrayList<Integer> xList = new ArrayList<Integer>();
 14     ArrayList<Integer> yList = new ArrayList<Integer>();
 15     ArrayList<Integer> widthList = new ArrayList<Integer>();
 16     ArrayList<Integer> heightList = new ArrayList<Integer>();
 17     
 18     static Music m;
 19     public static void main(String[] args) {
 20         m = new Music();
 21     }
 22     // 构造函数
 23     Music() {
 24         frame = new JFrame("绘制删除方块");
 25         JButton drawButton = new JButton("绘制");
 26         JButton clearButton = new JButton("清屏");
 27         JButton backButton = new JButton("回退");
 28         drawButton.addActionListener(new DrawListener());
 29         clearButton.addActionListener(new ClearListener());
 30         backButton.addActionListener(new BackListener());
 31         
 32         JPanel panel = new JPanel();
 33         panel.add(drawButton);
 34         panel.add(backButton);
 35         panel.add(clearButton);
 36         
 37         frame.getContentPane().add(BorderLayout.SOUTH, panel);
 38         frame.getContentPane().add(this);
 39         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 40         frame.setSize(800, 600);
 41         frame.setVisible(true);
 42     }
 43     
 44     public void paint(Graphics g) {
 45         // 绘图
 46         if (isDraw) {
 47             int red = (int)(Math.random() * 255);
 48             int green = (int)(Math.random() * 255);
 49             int blue = (int)(Math.random() * 255);
 50         
 51             int x = (int)(Math.random() * 700);
 52             int y = (int)(Math.random() * 500);
 53             int width = (int)(Math.random() * 101);
 54             int height = (int)(Math.random() * 101);
 55         
 56             Color randColor = new Color(red, green, blue);
 57             
 58             xList.add(x);
 59             yList.add(y);
 60             widthList.add(width);
 61             heightList.add(height);
 62             colorList.add(randColor);
 63             
 64             for (int i = 0; i < xList.size(); i++) {
 65                 g.setColor(colorList.get(i));
 66                 g.fillRect(xList.get(i), yList.get(i), widthList.get(i), heightList.get(i));
 67             }
 68             isDraw = false;
 69         }    
 70         // 防止拉长窗口的时候图像消失或者改变
 71         else {
 72             for (int i = 0; i < xList.size(); i++) {
 73                 g.setColor(colorList.get(i));
 74                 g.fillRect(xList.get(i), yList.get(i), widthList.get(i), heightList.get(i));
 75             }
 76         }
 77         // 回退
 78         try {
 79         if (isBack) {
 80             endIndex = xList.size() - 1;
 81             g.clearRect(xList.get(endIndex), yList.get(endIndex), widthList.get(endIndex), heightList.get(endIndex));
 82             colorList.remove(endIndex);
 83             xList.remove(endIndex);
 84             yList.remove(endIndex);
 85             widthList.remove(endIndex);
 86             heightList.remove(endIndex);
 87             isBack = false;
 88         } 
 89         } catch (ArrayIndexOutOfBoundsException ex) {System.out.println("你的异常已送达"); ex.printStackTrace();}
 90         // 清屏  ————注意不能在迭代数组的同时删除其元素
 91         if (isClear) {
 92             listLength = xList.size();
 93             for (int i = 0; i < listLength; i++) { 
 94                 g.clearRect(xList.get(0), yList.get(0), widthList.get(0), heightList.get(0));
 95                 colorList.remove(0);
 96                 xList.remove(0);
 97                 yList.remove(0);
 98                 widthList.remove(0);
 99                 heightList.remove(0);
100             }
101             isClear = false;
102         }
103         
104        
105     }
106     // 绘图接口
107     class DrawListener implements ActionListener {
108         public void actionPerformed(ActionEvent event) {
109             isDraw = true;
110             frame.repaint();
111         }
112     }
113     // 撤销接口
114     class BackListener implements ActionListener {
115         public void actionPerformed(ActionEvent event) {
116             isBack  = true;
117             frame.repaint();
118         }
119     }
120     // 清屏接口
121     class ClearListener implements ActionListener {
122         public void actionPerformed(ActionEvent event) {
123             isClear = true;
124             frame.repaint();
125         }
126     }
127     
128 }
绘制撤销与清屏

 

以上是关于Swing 4方块绘制删除与多按钮监听的主要内容,如果未能解决你的问题,请参考以下文章

Swing事件监听

Java Swing:在 JPanel 的组件下绘制?

高级特性- 高级Swing

java GUI编程(swing)之七swing事件监听

java中鼠标监听器的使用

Java Swing 程序设计03