Java 直线、多段线画板 PaintJFrame (整理)

简介: 1 package demo; 2 3 4 5 import java.awt.BorderLayout; 6 import java.awt.Color; 7 import java.
  1 package demo;
  2 
  3 
  4 
  5 import java.awt.BorderLayout;
  6 import java.awt.Color;
  7 import java.awt.FlowLayout;
  8 import java.awt.Graphics;
  9 import java.awt.Toolkit;
 10 import java.awt.event.MouseAdapter;
 11 import java.awt.event.MouseEvent;
 12 import java.awt.event.MouseMotionAdapter;
 13 import java.util.Arrays;
 14 
 15 import javax.swing.JButton;
 16 import javax.swing.JFrame;
 17 import javax.swing.JPanel;
 18 /**
 19 *                           Java 直线、多段线画板 PaintJFrame (整理)
 20 * 
 21 *                                          2016-1-2 深圳 南山平山村 曾剑锋
 22 *
 23 * <p>
 24 * <h4>一、软件声明:</h4><br>
 25 * <p>&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp
 26 *           本软件是仿AutoCAD部分功能软件,最初设计之初的想法是:实现各种图形的绘制(直线、多段线、圆、写轮眼)。但是
 27 *       当实现到了目前的状态的时候发现后面的程序开发只不过是对当前程序的复制、粘贴,而且最终绘制出来的图形看上去并不是
 28 *       很精细、优雅,就如同当您在使用本软件的时候会发现,绘制出来的直线是那种很让人纠结的线,不够平滑的感觉,至少她让
 29 *       我本人感觉不是太舒服的感觉。
 30 * </p>
 31 * <p>&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp
 32 *             同时如果在软件中添加过多的东西,会让人觉的更难以阅读理解,不适合用来沟通交流,尤其是像这种只能通过文字沟通
 33 *         的方式,所以本人不打算对此软件进行进一步的扩展。
 34 * </p>
 35 * <h4>二、软件结构如下:</h4><br><ol>
 36 *             <li>所有类的继承关系如下:<br>
 37 *             <ul><li>绘图类继承关系:<br>
 38 *                     |--Shape<br>
 39 *                     |--|--SingleLine<br>
 40 *                     |--|--MultiLine<br>
 41 *                 <li>按钮类继承关系(括号内为添加的监听事件):<br>
 42 *                     |--JButton<br>
 43 *                     |--|--PaintJButton<br>
 44 *                     |--|--|--SingleJButton(MouseAdapter)<br>
 45 *                     |--|--|--MultiJButton(MouseAdapter)<br>
 46 *                 <li>窗口类继承关系:<br>
 47 *                     |--JFrame<br>
 48 *                     |--|--PaintJFrame<br>
 49 *                 <li>绘图面板继承关系(PaintJFrame的内部类,括号内为添加的监听事件):<br>
 50 *                     |--JPanel<br>
 51 *                     |--PaintJPanel(MouseAdapter,MouseMotionAdapter)<br>
 52 *             </ul>
 53 *             <li>绘图类与按钮来的逻辑关系如下:
 54 *             <ul><li>SingleLine和SingleJButton是对应的;
 55 *                 <li>MultiLine和MultJButton是对应的;
 56 *                 <li>当按下SingleJButton时,就能够在面板上绘制SingleLine;
 57 *                 <li>当按下MultJButton时,就能够在面板上绘制MultiLine;
 58 *             </ul>
 59 *             <li>GUI图形界面容器、组件的包含关系:<br>
 60 *             <ul>
 61 *                 |--PaintJFrame(窗口容器,位于main函数中,BorderLayout布局)<br>
 62 *                 |--|--buttonJPanel(JPanel容器,全局变量,FlowLayout布局)<br>
 63 *                 |--|--|--singleLineJButton(绘直线按钮,paintJButtons数组中下标为0的位置)<br>
 64 *                 |--|--|--multiLineJButton(绘多段线按钮,paintJButtons数组中下标为1的位置)<br>
 65 *                 |--|--paintJPanel(JPanel画板,全局变量)<br>
 66 *             </ul>    
 67 * </ol>    
 68 */
 69 public class PaintJFrame extends JFrame{
 70     private static final long serialVersionUID = 1L;
 71     /**
 72      * &nbsp &nbsp &nbsp &nbsp
 73      *      主要用于保存所画图的类型,如:直线、多样线等内容,可以认为是一个容器,包含所有的图形的基本信息,
 74      * 每次当前绘制的图形都保存在shapes的最后一个位置上,主要是为了便于查找。
 75      */
 76     Shape[] shapes = {};
 77     /**
 78      * 定义一个绘图面板,主要用于绘图
 79      */
 80     PaintJPanel paintJPanel    = new PaintJPanel();
 81     /**
 82      * 定义一个按钮面板,主要用于放置按钮
 83      */
 84     JPanel buttonJPanel = new JPanel(new FlowLayout());
 85     /**
 86      * 主要用于保存动态的X轴坐标,通过鼠标移动监听器来获取
 87      */
 88     int trendsX = 0;
 89     /**
 90      * 主要用于保存动态的Y轴坐标,通过鼠标移动监听器来获取
 91      */
 92     int trendsY = 0;
 93     /**
 94      * 主要用于保存点击时的X轴坐标,通过鼠标移动监听器来获取
 95      */
 96     int clickX = 0;
 97     /**
 98      * 主要用于保存点击时的Y轴坐标,通过鼠标移动监听器来获取
 99      */
100     int clickY = 0;
101     /**
102      * 用于放置各种按钮,主要用于凸现当前绘图时的按钮,方便查找,修改
103      */
104     PaintJButton[] paintJButtons = new PaintJButton[2];
105     /**
106      * <h4>窗口构造函数功能如下:</h4><br><ol>
107      *         <li>setButtonJPanel();设置按钮面板,主要是添加一些需要的按钮在其中;
108      *         <li>setJFrame();设置窗口属性,主要是窗口的一些基本属性设置;
109      *         <li>paintJPanel.startRun();启动paintJPanel内部线程,主要用于对画板中图形的计算以及重绘
110      * </ol>
111      */
112     public PaintJFrame() {
113         setButtonJPanel();
114         setJFrame();
115         paintJPanel.startRun();
116     }
117     /**
118      * <h4>设置按钮面板函数功能如下:</h4><br><ol>
119      *         <li>创建一个绘制直线的按钮,名字为:直线;
120      *         <li>创建一个绘制多段线的按钮,名字为:多段线;
121      *         <li>将直线按钮加入paintJButtons[0]中,主要是因为直线按钮对应PaintJButton.SINGLE_LINE;
122      *             将多段线按钮加入paintJButtons[1]中,主要是因为直线按钮对应PaintJButton.MULTI_LINE
123      *         <li>将两个按钮添加进入buttonJPanel。
124      * <ol>
125      */
126     private void setButtonJPanel() {
127         PaintJButton singleLineJButton = new SingleJButton("直线");
128         PaintJButton multiLineJButton = new MultiJButton("多段线");
129         paintJButtons[PaintJButton.SINGLE_LINE] = singleLineJButton;
130         paintJButtons[PaintJButton.MULTI_LINE] = multiLineJButton;
131         buttonJPanel.add(singleLineJButton);
132         buttonJPanel.add(multiLineJButton);
133     }
134     /**
135      * <h4>窗体设置函数功能如下:</h4><br><ol>
136      *         <li>设置窗体布局格式;
137      *         <li>设置窗体标题;
138      *         <li>设置窗体大小;
139      *         <li>设置窗体关闭模式;
140      *         <li>设置窗体位置;
141      *         <li>将paintJPanel,buttonJPanel加入窗体相应位置
142      *         <li>将窗体设置为可见;
143      * </ol>
144      */
145     private void setJFrame() {
146         this.setLayout(new BorderLayout());
147         this.setTitle("Painting");
148         this.setSize(1024, 600);
149         this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
150         this.setLocationRelativeTo(null);
151         this.setLocation(    (int)((Toolkit.getDefaultToolkit().getScreenSize().getWidth()-1024)/2),
152                             (int)((Toolkit.getDefaultToolkit().getScreenSize().getHeight()-600)/2));
153         this.add(BorderLayout.CENTER,paintJPanel);
154         this.add(BorderLayout.NORTH,buttonJPanel);
155         this.setVisible(true);
156     }
157     /**
158      * <h4>PaintJPanel类设计思路:</h4><br><ol>
159      *         这是一个绘图面板,只与图形显示和鼠标点击、移动相关;<br><br>
160      *         <li>在图形显示方面:</li>
161      *         <ul><li>重写paint()方法;
162      *             <li>添加线程来动态维护图形显示。
163      *         </ul>
164      *         <li>需要在这个类中添加事件监听事件:
165      *         <ul><li>鼠标点击,本类使用了MouseAdapter;
166      *             <li>鼠标移动事件,本类使用了MouseMotionAdapter。
167      *         </ul>
168      * </ol>
169      */
170     class PaintJPanel extends JPanel {
171         private static final long serialVersionUID = 1L;
172         /**
173          * <h4>PaintJPanel构造方法功能如下:</h4><br><ol>
174          *         <li>为PaintJPanel添加MouseAdapter事件;
175          *         <li>为PaintJPanel添加MouseMotionAdapter事件。
176          * </ol>
177          */
178         public PaintJPanel() {    
179             this.addMouseListener(new MouseAdapter() {
180                 @Override
181                 public void mouseClicked(MouseEvent e) {
182                     clickX = e.getX();
183                     clickY = e.getY();
184                     dealWithClick(e);
185                 }
186             });
187             this.addMouseMotionListener(new MouseMotionAdapter() {
188                 @Override
189                 public void mouseMoved(MouseEvent e) {
190                     trendsX = e.getX();
191                     trendsY = e.getY();
192                     setDynamicPoint();
193                 }
194             });
195         }
196         /**
197          * <h4>设置动态点函数功能如下:</h4><br><ol>
198          *         <li>如果当前绘制的是直线
199          *         <ul><li>判断是否当前是绘制直线的第二个点,因为,第一个点不需要动态效果;
200          *             <li>由于当前所绘制的图形信息保存在shapes最后一个位置上,所以快速找到那个对象;
201          *             <li>如果是,则设置直线的第二个点。</ul>
202          *         <li>如果当前绘制的是多段线
203          *         <ul><li>判断是否当前是绘制多段线非第一个点,因为,第一个点不需要动态效果;
204          *             <li>由于当前所绘制的图形信息保存在shapes最后一个位置上,所以快速找到那个对象;
205          *             <li>如果是,则设置将动态点加入多段线的pointX、pointY数组的末尾。</ul>
206          * </ol>        
207          */
208         private void setDynamicPoint() {
209             if (PaintJButton.currentButtonFlag == PaintJButton.SINGLE_LINE) {
210                 if (SingleLine.clickCount == 1) {
211                     SingleLine singleLine = (SingleLine)shapes[shapes.length-1];
212                     singleLine.setSecondPoint(trendsX, trendsY);
213                 }
214             }if (PaintJButton.currentButtonFlag == PaintJButton.MULTI_LINE) {
215                 if (MultiLine.clickCount != 0) {
216                     MultiLine multiLine = (MultiLine)shapes[shapes.length-1];
217                     multiLine.pointX[MultiLine.clickCount] = trendsX;
218                     multiLine.pointY[MultiLine.clickCount] = trendsY;
219                 }
220             }
221         }
222         /**
223          * <h4>处理点击函数功能如下:</h4><br><ol>
224          *         <li>如果是鼠标左击事件,进入左击函数处理左击相关事务;
225          *         <li>如果是鼠标中键事件,直接处理;
226          *         <li>如果是鼠标右击事件,进入右击函数处理右击相关事务。
227          * </ol>
228          */
229         private void dealWithClick(MouseEvent e) {
230             if (e.getButton() == MouseEvent.BUTTON1) {
231                 leftClick();
232             }else if (e.getButton() == MouseEvent.BUTTON2) {
233                 System.out.println("您点了鼠标中间( ^_^ )");
234             }else if (e.getButton() == MouseEvent.BUTTON3) {
235                 rightClick();
236             }        
237         }
238         /**
239          * <h4>右击函数</h4><br><ol>
240          *         右击函数是用于结束当前绘图状态,相当于鼠标右键结束本次绘图环境:<br><br>
241          *         <li>如果当前绘制的是直线:
242          *         <ul><li>右击处理近针对非第一次点击,如果没有开始绘图,没必要结束本次绘图;
243          *             <li>因为是直线,取消绘图,相当于直接抛弃当前直线就行了;
244          *             <li>同时需要将直线的全局变量clickCount置0,为下一次绘图作准备。</ul>
245          *         <li>如果当前绘图的是多段线:
246          *         <ul><li>右击处理近针对非第一次点击,如果没有开始绘图,没必要结束本次绘图;
247          *             <li>因为是多段线,取消绘图,相当于直接抛弃最后一个点就行了;
248          *             <li>同时需要将多段线的全局变量clickCount置0,为下一次绘图作准备。</ul>
249          * </ol>
250          */
251         private void rightClick() {
252             if (PaintJButton.currentButtonFlag == PaintJButton.SINGLE_LINE) {
253                 if (SingleLine.clickCount != 0) {
254                     shapes = Arrays.copyOf(shapes, shapes.length-1);
255                 }
256                 SingleLine.clickCount = 0;
257             }else if (PaintJButton.currentButtonFlag == PaintJButton.MULTI_LINE) {
258                 if (MultiLine.clickCount != 0) {
259                     MultiLine multiLine = (MultiLine)shapes[shapes.length-1];
260                     multiLine.setXYLengthUpDown(-1);
261                 }    
262                 MultiLine.clickCount = 0;    
263             }
264         }
265         /**
266          * <h4>左击函数功能如下:</h4><br><ol>
267          *         左击函数,主要用于给当前选定的图形添加坐标点相关信息:<br><br>
268          *
269          *         <li>如果当前绘制的图形是直线,进入直线左击函数处理相关的事务;
270          *         <li>如果当前绘制的图形是多段线,进入多段线左击函数处理相关的事务。
271          * </ol>
272          */
273         private void leftClick() {
274             if (PaintJButton.currentButtonFlag == PaintJButton.SINGLE_LINE) {
275                 leftClickForSingleLine();
276             }else if (PaintJButton.currentButtonFlag == PaintJButton.MULTI_LINE) {
277                 leftClickForMutiLine();
278             }
279         }
280         /**
281          * <h4>多段线左击函数功能如下:</h4><br><ol>
282          *         <li>如果是第一次点击:
283          *         <ul><li>shapes长度+1;
284          *             <li>新建多段线对象;
285          *             <li>将新建的对象放入shapes最后;
286          *             <li>将当前鼠标点击的坐标放入多段线第一个坐标值中
287          *             <li>点击次数+1;</ul>
288          *         <li>如果不是第一次点击:
289          *         <ul><li>点击次数+1;
290          *             <li>从shapes最后一个位置取出多段线对象;
291          *             <li>将当前鼠标点击的坐标放入多段线对应坐标值中</ul>
292          *     </ol>
293          */
294         private void leftClickForMutiLine() {
295             if (MultiLine.clickCount == 0) {
296                 shapes = Arrays.copyOf(shapes, shapes.length+1);
297                 MultiLine multiLine = new MultiLine();
298                 shapes[shapes.length-1] = multiLine;
299                 multiLine.setFirstPoint(clickX, clickY);
300                 MultiLine.clickCount++;
301             }else {
302                 MultiLine.clickCount++;
303                 MultiLine multiLine = (MultiLine)shapes[shapes.length-1];
304                 multiLine.setOtherPoint(clickX, clickY);
305             }
306         }
307         /**
308          * <h4>直线左击函数功能如下:</h4>
309          *         <li>如果是第一次点击:
310          *         <ul><li>shapes长度+1;
311          *             <li>新建直线对象;
312          *             <li>将新建的对象放入shapes最后;
313          *             <li>将当前鼠标点击的坐标放入多段线第一个坐标值中
314          *             <li>将当前鼠标点击的坐标放入多段线第二个坐标值中,消除原点坐标影响
315          *             <li>点击次数+1;</ul>
316          *         <li>如果不是第一次点击:
317          *         <ul><li>从shapes最后一个位置取出直线对象;
318          *             <li>将当前鼠标点击的坐标放入直线对应坐标值中
319          *             <li>点击次数清零;</ul>
320          *     </ol>
321          */
322         private void leftClickForSingleLine() {
323             if (SingleLine.clickCount == 0) {
324                 shapes = Arrays.copyOf(shapes, shapes.length+1);
325                 SingleLine singleLine = new SingleLine();
326                 shapes[shapes.length-1] = singleLine;
327                 singleLine.setFirstPoint(clickX, clickY);
328                 singleLine.setSecondPoint(clickX, clickY);
329                 SingleLine.clickCount++;
330             }else {
331                 SingleLine singleLine = (SingleLine)shapes[shapes.length-1];
332                 singleLine.setSecondPoint(clickX, clickY);
333                 SingleLine.clickCount = 0;
334             }
335         }
336         /**
337          * <h4>重写paint方法</h4><br><ol>
338          *         <li>调用父类paint方法;
339          *         <li>设置背景色:黑色;
340          *         <li>将shapes数组中的图形绘出来。
341          * </ol>
342          */
343         @Override
344         public void paint(Graphics graphics) {
345             super.paint(graphics);
346             this.setBackground(Color.black);
347             for (int i = 0; i < shapes.length; i++) {
348                 shapes[i].show(graphics, Color.white);
349             }
350         }
351         /**
352          * <h4>startRun方法功能如下:</h4><br><ol>
353          *         创建一个线程用于维护PaintJPanel所需的一些动态效果:<br><br>
354          *             <li>用于改变当前选择绘制的图形按钮,高亮突出显示,容易辨别,只有当两个标志不相同时
355          *                 才改变颜色,相同表示同一个按钮多次点击,主要是为了解决对同一个按钮多次点击的问题;
356          *             <li>50ms将图形刷新一次。
357          * </ol>
358          */
359         public void startRun() {
360             new Thread(){
361                 public void run() {    
362                     while (true) {
363                         if (PaintJButton.preButtonFlag != PaintJButton.currentButtonFlag) {
364                             paintJButtons[PaintJButton.preButtonFlag].setBackground(Color.white);
365                         }
366                         try {
367                             Thread.sleep(50);
368                         } catch (InterruptedException e) {
369                             e.printStackTrace();
370                         }
371                         repaint();
372                     }
373                 };
374             }.start();
375         }
376     }
377     public static void main(String[] args) {
378         new PaintJFrame();
379     }
380 }
381 
382 /**
383  * <h4>一、本类设计思路如下:</h4><br><ol>
384  *         <li>本类主要用于保存各种图形的基本形状信息;
385  *         <li>仅针对目前的需求,如直线、多段线,提供保存X,Y轴坐标信息,一些基本方法.
386  * <ol>
387  */
388 abstract class Shape {
389     /** x轴数列,默认长度为1 */
390     int[] pointX = { 0 };
391     /** Y轴数列,默认长度为1 */
392     int[] pointY = { 0 };
393     public Shape() {
394     }
395     public Shape(int pointX,int pointY) {
396         this.pointX[0] = pointX;
397         this.pointY[0] = pointY;
398     }
399     /** 抽象方法,因为每个图形都应该有自己的绘图方法 */
400     public abstract void show(Graphics graphics,Color color);
401     @Override
402     public String toString() {
403         return "pointX:"+Arrays.toString(pointX)+"\npointY:"+Arrays.toString(pointY);
404     }
405 }
406 
407 /**
408  * <h4>本类设计思路如下:</h4><br><ol>
409  *         <li>继承自Shape类;
410  *        <li>一条直线有两个坐标点;
411  *        <li>实现show方法;
412  *        <li>static int clickcount = 0;用一个静态变量确定鼠标点击的次数,方便绘图时
413  *                确定当前所处的绘图状态。
414  * </ol>
415  */
416 class SingleLine extends Shape{
417     /** 主要用于解决在绘制单条线的时候,当前鼠标点击是第一次点击,还是第二次点击 */
418     public static int clickCount = 0;
419     public SingleLine() {
420         this.pointX = Arrays.copyOf(this.pointX, this.pointX.length+1);
421         this.pointY = Arrays.copyOf(this.pointY, this.pointY.length+1);
422     }
423     /**
424      * 设置直线第一个点坐标
425      */
426     public void setFirstPoint(int pointX_0, int pointY_0) {
427         pointX[0] = pointX_0;
428         pointY[0] = pointY_0;
429     }
430     /**
431      * 设置直线第二个点坐标
432      */
433     public void setSecondPoint(int pointX_1,int pointY_1) {
434         pointX[1] = pointX_1;
435         pointY[1] = pointY_1;
436     }
437     @Override
438     public void show(Graphics graphics, Color color) {
439         graphics.setColor(color);
440         graphics.drawLine(pointX[0], pointY[0], pointX[1], pointY[1]);
441     }
442     @Override
443     public String toString() {
444         return "pointX"+Arrays.toString(pointX)+"\n"+"pointY"+Arrays.toString(pointY);
445     }
446 }
447 
448 /**
449  * <h4>本类设计思路如下:</h4><br><ol>
450  *         <li>继承自Shape类;
451  *        <li>一条多段线有多个坐标点;
452  *        <li>实现show方法;
453  *        <li>static int clickcount = 0;用一个静态变量确定鼠标点击的次数,方便绘图时
454  *            确定当前所处的绘图状态。
455  *</ol>
456  */
457 class MultiLine extends Shape{
458     /** 主要用于解决在绘制单条线的时候,当前鼠标点击是第一次点击,还是第几次点击 */
459     public static int clickCount = 0;
460     public MultiLine() {
461     }
462     /** 在创建MultiLine以后,加入第一个点的时候,pointX,pointY长度加+1 */
463     public void setFirstPoint(int pointX_0, int pointY_0) {
464         this.pointX = Arrays.copyOf(this.pointX, this.pointX.length+1);
465         this.pointY = Arrays.copyOf(this.pointY, this.pointY.length+1);
466         pointX[0] = pointX_0;
467         pointY[0] = pointY_0;
468         pointX[1] = pointX_0;
469         pointY[1] = pointY_0;
470     }
471     /**
472      * 每次多段线上多出一个点时,数组长度+1,并赋予相应的值
473      */
474     public void setOtherPoint(int pointX_1,int pointY_1) {
475         this.pointX = Arrays.copyOf(this.pointX, this.pointX.length+1);
476         this.pointY = Arrays.copyOf(this.pointY, this.pointY.length+1);
477         pointX[pointX.length-2] = pointX_1;
478         pointY[pointY.length-2] = pointY_1;
479         pointX[pointX.length-1] = pointX_1;
480         pointY[pointY.length-1] = pointY_1;
481     }
482     /**
483      * 增加或者截取pointX,pointY长度
484      */
485     public void setXYLengthUpDown(int x) {
486         this.pointX = Arrays.copyOf(this.pointX, this.pointX.length+x);
487         this.pointY = Arrays.copyOf(this.pointY, this.pointY.length+x);
488     }
489     @Override
490     public void show(Graphics graphics, Color color) {
491         graphics.setColor(color);
492         for (int i = 0; i < pointX.length-1; i++) {
493             graphics.drawLine(pointX[i], pointY[i], pointX[i+1], pointY[i+1]);
494         }
495     }
496     @Override
497     public String toString() {
498         return "pointX"+Arrays.toString(pointX)+"\n"+"pointY"+Arrays.toString(pointY);
499     }
500 }
501 
502 /**
503  * <h4>一、本类设计思路如下:</h4><br><ol>
504  *         <li>通过选择不同的按钮来绘制不同的图形;
505  *         <li>通过改变当前按键的背景色来区分当前选中的按钮和未被选中的按钮.
506  * </ol>
507  * <h4>二、解决方案如下:</h4><br><ol>
508  *      <li>使用"静态"的数据来保存当前所选择的按钮(currentButtonFlag);
509  *      <li>为了保证上一次的按钮能恢复到没有按下的状态的颜色,,所以又需要一个
510  *              "静态"的数据来保存前一次所选择的按钮(preButtonFlag);
511  *      <li>常量SINGLE_LINE表示直线,常量MULTI_LINE表示多段线.
512  * </ol>
513  */
514 class PaintJButton extends JButton{
515     private static final long serialVersionUID = 1L;
516     /** 用于保存上一次点击的按键的标志 */
517     static int preButtonFlag = 0;
518     /** 用于保存当前正在使用的按键标志 */
519     static int currentButtonFlag = 0;
520     /** 直线的标志 */
521     public static final int SINGLE_LINE = 0;
522     /** 多段线的标志 */
523     public static final int MULTI_LINE = 1;
524     public PaintJButton() {
525     }
526     public PaintJButton(String string) {
527         super(string);    
528     }
529 }
530 
531 /**
532  * <h4>一、本类设计思路如下:</h4><br><ol>
533  *         <li>本类继承自PaintJButton;
534  *      <li>为本类添加按钮响应事件;
535  *      <ul><li>preButtonFlag = currentButtonFlag;将当前的按键标志赋给前一次的按键标志;
536  *          <li>currentButtonFlag = SINGLE_LINE;并将当前的按键标志改成多段线对应的按键值;
537  *          <li>setBackground(Color.red);改变当前按键的背景色。
538  *        </ul>
539  *</ol>
540  */
541 final class SingleJButton extends PaintJButton {
542 
543     private static final long serialVersionUID = 1L;
544     public SingleJButton() {
545         addMouseAdepter();
546     }
547     public SingleJButton(String string) {
548         super(string);
549         addMouseAdepter();
550     }
551     /**
552      * <h4>添加鼠标适配器</h4><br><ol>
553      *         用于添加鼠标点击事件:
554      *         <li>如果curentButtonFlag保存的当前的按钮标志,所以当点击一个按钮时,currentButtonFlag
555      *                 保存的值边成了前一个按钮的值,而这个值应该由preButtonFlag来保存。
556      *         <li>将currentButtonFlag设置成SingleJButton对应的SINGLE_LINE值;
557      *         <li>将按钮颜色设置为红色。
558      * </ol>
559      */
560     private void addMouseAdepter() {
561         this.addMouseListener(new MouseAdapter() {
562             @Override
563             public void mouseClicked(MouseEvent e) {
564                 preButtonFlag = currentButtonFlag;
565                 currentButtonFlag = SINGLE_LINE;
566                 setBackground(Color.red);
567             }
568         });    
569     }
570 }
571 
572 /**
573  * <h4>一、本类设计思路如下:</h4><br><ol>
574  *         <li>本类继承自PaintJButton;
575  *      <li>为本类添加按钮响应事件;
576  *      <ul><li>preButtonFlag = currentButtonFlag;将当前的按键标志赋给前一次的按键标志;
577  *          <li>currentButtonFlag = MULTI_LINE;并将当前的按键标志改成多段线对应的按键值;
578  *          <li>setBackground(Color.red);改变当前按键的背景色.
579  *      </ul>
580  * </ol>
581  */
582 final class MultiJButton extends PaintJButton{
583     private static final long serialVersionUID = 1L;
584     public MultiJButton() {
585         addMouseAdapter();
586     }
587     public MultiJButton(String string) {
588         super(string);
589         addMouseAdapter();
590     }
591     /**
592      * <h4>添加鼠标适配器</h4><br><ol>
593      *         用于添加鼠标点击事件:
594      *         <li>如果curentButtonFlag保存的当前的按钮标志,所以当点击一个按钮时,currentButtonFlag
595      *                 保存的值边成了前一个按钮的值,而这个值应该由preButtonFlag来保存。
596      *         <li>将currentButtonFlag设置成MultiJButton对应的MULTI_LINE值;
597      *         <li>将按钮颜色设置为红色。
598      * </ol>
599      */
600     private void addMouseAdapter() {
601         this.addMouseListener(new MouseAdapter() {
602             @Override
603             public void mouseClicked(MouseEvent e) {
604                 preButtonFlag = currentButtonFlag;
605                 currentButtonFlag = MULTI_LINE;
606                 setBackground(Color.red);
607             }
608         });
609     }
610 }

 

目录
相关文章
|
存储 算法 Java
第十二届蓝桥杯A组省赛填空题Java思路及代码合集(相乘直线货物摆放路径回路计数)
第十二届蓝桥杯A组省赛填空题Java思路及代码合集(相乘直线货物摆放路径回路计数)
229 0
|
10天前
|
存储 Java 数据库连接
java多线程之线程通信
java多线程之线程通信
|
10天前
|
算法 Java 开发者
Java中的多线程编程:概念、实现与性能优化
【4月更文挑战第9天】在Java编程中,多线程是一种强大的工具,它允许开发者创建并发执行的程序,提高系统的响应性和吞吐量。本文将深入探讨Java多线程的核心概念,包括线程的生命周期、线程同步机制以及线程池的使用。接着,我们将展示如何通过继承Thread类和实现Runnable接口来创建线程,并讨论各自的优缺点。此外,文章还将介绍高级主题,如死锁的预防、避免和检测,以及如何使用并发集合和原子变量来提高多线程程序的性能和安全性。最后,我们将提供一些实用的性能优化技巧,帮助开发者编写出更高效、更稳定的多线程应用程序。
|
8天前
|
安全 算法 Java
深入理解Java并发编程:线程安全与性能优化
【4月更文挑战第11天】 在Java中,高效的并发编程是提升应用性能和响应能力的关键。本文将探讨Java并发的核心概念,包括线程安全、锁机制、线程池以及并发集合等,同时提供实用的编程技巧和最佳实践,帮助开发者在保证线程安全的前提下,优化程序性能。我们将通过分析常见的并发问题,如竞态条件、死锁,以及如何利用现代Java并发工具来避免这些问题,从而构建更加健壮和高效的多线程应用程序。
|
1天前
|
安全 Java
java多线程(一)(火车售票)
java多线程(一)(火车售票)
|
2天前
|
安全 Java 调度
Java并发编程:深入理解线程与锁
【4月更文挑战第18天】本文探讨了Java中的线程和锁机制,包括线程的创建(通过Thread类、Runnable接口或Callable/Future)及其生命周期。Java提供多种锁机制,如`synchronized`关键字、ReentrantLock和ReadWriteLock,以确保并发访问共享资源的安全。此外,文章还介绍了高级并发工具,如Semaphore(控制并发线程数)、CountDownLatch(线程间等待)和CyclicBarrier(同步多个线程)。掌握这些知识对于编写高效、正确的并发程序至关重要。
|
2天前
|
安全 Java 程序员
Java中的多线程并发编程实践
【4月更文挑战第18天】在现代软件开发中,为了提高程序性能和响应速度,经常需要利用多线程技术来实现并发执行。本文将深入探讨Java语言中的多线程机制,包括线程的创建、启动、同步以及线程池的使用等关键技术点。我们将通过具体代码实例,分析多线程编程的优势与挑战,并提出一系列优化策略来确保多线程环境下的程序稳定性和性能。
|
2天前
|
缓存 分布式计算 监控
Java并发编程:深入理解线程池
【4月更文挑战第17天】在Java并发编程中,线程池是一种非常重要的技术,它可以有效地管理和控制线程的执行,提高系统的性能和稳定性。本文将深入探讨Java线程池的工作原理,使用方法以及在实际开发中的应用场景,帮助读者更好地理解和使用Java线程池。
|
3天前
|
存储 安全 Java
Java中的容器,线程安全和线程不安全
Java中的容器,线程安全和线程不安全
10 1
|
3天前
|
Java 开发者
Java中多线程并发控制的实现与优化
【4月更文挑战第17天】 在现代软件开发中,多线程编程已成为提升应用性能和响应能力的关键手段。特别是在Java语言中,由于其平台无关性和强大的运行时环境,多线程技术的应用尤为广泛。本文将深入探讨Java多线程的并发控制机制,包括基本的同步方法、死锁问题以及高级并发工具如java.util.concurrent包的使用。通过分析多线程环境下的竞态条件、资源争夺和线程协调问题,我们提出了一系列实现和优化策略,旨在帮助开发者构建更加健壮、高效的多线程应用。
3 0