首页 > 代码库 > 【Swing 4】方块绘制、删除与多按钮监听

【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());  // 如果这里变成g.fillRect(), 那么则是设置背景颜色
29         
30         g.setColor(randColor);                                
31         g.fillOval(200, 150, 50, 50);                         // 设置椭圆, 参数依旧是左上角坐标和长宽
32         g.setColor(randColor);
33         g.fillOval(400, 150, 50, 50);
34         
35     }
36 }

技术分享

 

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

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

技术分享

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

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

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

  版本二

 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     boolean isMove = true;                                    // 添加控制画图函数执行的布尔变量
 9     public static void main(String[] args) {
10         new Test();                                           // 创建Test对象, 实际是调用构造函数
11     }
12     
13     Test() {                                                  // 构造函数在类实例化时(使用new方法)被调用           
14         JFrame frame = new JFrame("猜猜我是谁");                          // (对象是类的实体/实例)
15         
16         frame.getContentPane().add(this);                       // 添加JPanel及其组件
17         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置关闭窗口时退出javaw.exe进程
18         frame.setSize(600, 500);                              // 窗口大小设为宽800像素, 高600像素
19         frame.setVisible(true);                   
20     }
21     
22     public void paintComponent(Graphics g) {                  // paintComponent()是电脑自己会执行的方法
23         if (isMove) {
24             int red = (int)(Math.random() * 255);
25             int green = (int)(Math.random() * 255);
26             int blue = (int)(Math.random() * 255);
27         
28             Color randColor = new Color(red, green, blue);        // 红绿蓝是三原色, 由它们混合产生其它颜色
29             g.setColor(Color.pink);
30             g.fillOval(0, 0, this.getWidth(), this.getHeight());  // 如果这里变成g.fillRect(), 那么则是设置背景颜色
31         
32             g.setColor(randColor);                                
33             g.fillOval(200, 150, 50, 50);                         // 设置椭圆, 参数依旧是左上角坐标和长宽
34             g.setColor(randColor);
35             g.fillOval(400, 150, 50, 50);
36             isMove = false;                                       // 执行一次画图函数后, isMove变为false 
37         }
38         
39     }
40 }

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

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

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

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

技术分享

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

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

  版本三

 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());  // 如果这里变成g.fillRect(), 那么则是设置背景颜色
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】方块绘制、删除与多按钮监听