JAVA 畫圖板實現(基本畫圖功能+界面UI)二、功能實現及重繪實現


上篇博客中介紹了界面的實現方法,在這篇博客中將對每個按鈕的功能的實現進行講解並介紹重繪

首先肯定要添加事件監聽機制了,那么問題來了,事件源對象是誰?需要添加什么方法?事件接口是什么?

1、我們需要點擊按鈕,獲取按鈕上的文字信息,顏色信息,粗細信息。那么,此時事件源對象就是按鈕,監聽方法就是addActionListener(ActionListener e),事件接口就是ActionListener

2、要根據在窗體上按下和釋放的位置畫一個圖形,此時事件源對象就是窗體,監聽方法就是addMouseListener(MouseListener e),事件接口就是MouseListener

 1 public class DrawListener extends MouseAdapter implements ActionListener {
 2 
 3     private Color color = Color.black;// 聲明顏色屬性,存儲用戶選擇的顏色
 4     private int width = 1;// 聲明粗細屬性,存儲用戶選擇的粗細
 5     private String type = "Line";// 聲明圖形屬性,存儲用戶選擇的圖形
 6     private int x1, y1, x2, y2, x3 = 0, y3 = 0, x4 = 0, y4 = 0, x5, y5;// 聲明坐標值屬性,存儲鼠標按下和釋放的坐標值
 7     private Graphics2D g;// 聲明畫筆類屬性,組件是畫出來的,現在要在組件上畫圖形,Graphics從組件上獲取
 8     private DrawMain dm;// 聲明畫圖程序窗體組件屬性
 9     private JTextField text;// 獲取文本框內容
10     private double H = 100;// 等腰三角形的高度
11     private int num = 0;
12     private List<Shape> list;
13     private ImageIcon i = new ImageIcon("C:\\Users\\long452a\\Desktop\\a1.jpg");
14 
15     /**
16      * 構造方法
17      * 
18      * @param dm畫圖程序的窗體組件對象
19      */
20     public DrawListener(DrawMain dm, JTextField text, List<Shape> list) {
21         this.dm = dm;
22         this.text = text;
23         this.list = list;
24     }
25 
26     /**
27      * 點擊按鈕時執行的事件處理方法
28      * 
29      * @param e對象中存儲了事件源對象的信息和動作信息
30      */
31     public void actionPerformed(ActionEvent e) {
32     }
33 
34     /**
35      * Invoked when the mouse button has been clicked (pressed and released) on a
36      * component.
37      */
38     public void mouseClicked(MouseEvent e) {
39     }
40 
41     /**
42      * Invoked when a mouse button has been pressed on a component.
43      */
44     public void mousePressed(MouseEvent e) {
45     }
46 
47     /**
48      * Invoked when a mouse button has been released on a component.
49      */
50     public void mouseReleased(MouseEvent e) {
51     }
52         
53     public void mouseDragged(MouseEvent e) {
54     }
55 }

這樣我們的類就建好了,下面就該寫里面的方法了

  1     /**
  2      * 點擊按鈕時執行的事件處理方法
  3      * 
  4      * @param e對象中存儲了事件源對象的信息和動作信息
  5      */
  6     public void actionPerformed(ActionEvent e) {
  7         String text = e.getActionCommand();
  8         if (text.equals("")) {
  9             JButton button = (JButton) e.getSource();
 10             color = button.getBackground();
 11         } else if (text.equals("1") || text.equals("3") || text.equals("5")) {
 12             width = Integer.parseInt(text);
 13         } else {
 14             type = text;
 15         }
 16         // System.out.println(color + ">>" + width + ">>" + type);
 17     }
 18 
 19     /**
 20      * Invoked when the mouse button has been clicked (pressed and released) on a
 21      * component.
 22      */
 23     public void mouseClicked(MouseEvent e) {
 24         x4 = x2;
 25         y4 = y2;
 26     }
 27 
 28     /**
 29      * Invoked when a mouse button has been pressed on a component.
 30      */
 31     public void mousePressed(MouseEvent e) {
 32         x1 = e.getX() + 7;
 33         y1 = e.getY() + 183;
 34         if (y1 < 183)
 35             y1 = 183;
 36         g = (Graphics2D) dm.getGraphics();// 從窗體上獲取畫筆對象
 37         g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);// 設置畫筆抗鋸齒
 38         g.setColor(color);// 設置畫筆顏色
 39         g.setStroke(new BasicStroke(width));// 設置畫筆線條粗細
 40 
 41     }
 42 
 43     /**
 44      * Invoked when a mouse button has been released on a component.
 45      */
 46     public void mouseReleased(MouseEvent e) {
 47         x2 = e.getX() + 7;
 48         y2 = e.getY() + 183;
 49         if (y2 < 183)
 50             y2 = 183;
 51         if (type.equals("iso_Tri")) {
 52             if (x1 == x2) {
 53                 g.drawLine(x1, y1, x2, y2);
 54                 g.drawLine(x1, y1, x1 + (int) H, (y2 + y1) / 2);
 55                 g.drawLine(x2, y2, x1 + (int) H, (y2 + y1) / 2);
 56                 list.add(new Shape(x1, y1, x2, y2, width, color, type, i, dm, text));
 57                 list.add(new Shape(x1, y1, x1 + (int) H, (y2 + y1) / 2, width, color, type, i, dm, text));
 58                 list.add(new Shape(x2, y2, x1 + (int) H, (y2 + y1) / 2, width, color, type, i, dm, text));
 59             } else if (y1 == y2) {
 60                 g.drawLine(x1, y1, x2, y2);
 61                 g.drawLine(x1, y1, (x1 + x2) / 2, y1 + (int) H);
 62                 g.drawLine(x2, y2, (x1 + x2) / 2, y1 + (int) H);
 63                 list.add(new Shape(x1, y1, x2, y2, width, color, type, i, dm, text));
 64                 list.add(new Shape(x1, y1, x1 + (x1 + x2) / 2, y1 + (int) H, width, color, type, i, dm, text));
 65                 list.add(new Shape(x2, y2, x1 + (x1 + x2) / 2, y1 + (int) H, width, color, type, i, dm, text));
 66             } else {
 67                 double a = Math.atan((double) (x2 - x1) / (double) (y2 - y1));
 68                 double x3 = (double) (x1 + x2) / 2 + H * Math.cos(a);
 69                 double y3 = (double) (y1 + y2) / 2 - H * Math.sin(a);
 70                 g.drawLine(x1, y1, x2, y2);
 71                 g.drawLine(x1, y1, (int) x3, (int) y3);
 72                 g.drawLine(x2, y2, (int) x3, (int) y3);
 73                 list.add(new Shape(x1, y1, x2, y2, width, color, type, i, dm, text));
 74                 list.add(new Shape(x1, y1, x1 + (int) x3, (int) y3, width, color, type, i, dm, text));
 75                 list.add(new Shape(x2, y2, (int) x3, (int) y3, width, color, type, i, dm, text));
 76             }
 77         } else if (type.equals("Polygon")) {
 78             if (num == 0) {
 79                 g.drawLine(x1, y1, x2, y2);
 80                 list.add(new Shape(x1, y1, x2, y2, width, color, type, i, dm, text));
 81                 x5 = x2;
 82                 y5 = y2;
 83             }
 84             num++;
 85             if (num == 1) {
 86                 x3 = x1;
 87                 y3 = y1;
 88             }
 89             if (x2 == x4 && y2 == y4) {
 90                 g.drawLine(x1, y1, x3, y3);
 91                 list.add(new Shape(x1, y1, x3, y3, width, color, type, i, dm, text));
 92                 num = 0;
 93             } else {
 94                 g.drawLine(x2, y2, x5, y5);
 95                 list.add(new Shape(x2, y2, x5, y5, width, color, type, i, dm, text));
 96                 x5 = x2;
 97                 y5 = y2;
 98             }
 99         } else {
100             Shape s = new Shape(x1, y1, x2, y2, width, color, type, i, dm, text);
101             s.draw(g);
102             list.add(s);
103         }
104     }
105 
106     public void mouseDragged(MouseEvent e) {
107         if (type.equals("Pencil")) {
108             x2 = e.getX() + 7;//這里的+7 +183 是調出來的,能夠使畫的圖是沿着鼠標
109             y2 = e.getY() + 183;
110             if (y2 < 183)
111                 y2 = 183;
112             Shape s = new Shape(x1, y1, x2, y2, width, color, type, i, dm, text);
113             s.draw(g);
114             list.add(s);
115             x1 = x2;
116             y1 = y2;
117         } else if (type.equals("Erase")) {
118             x2 = e.getX() + 7;
119             y2 = e.getY() + 183;
120             if (y2 < 183)
121                 y2 = 183;
122             Shape s = new Shape(x1, y1, x2, y2, width, Color.WHITE, type, i, dm, text);
123             s.draw(g);
124             list.add(s);
125             x1 = x2;
126             y1 = y2;
127         } else if (type.equals("噴槍")) // 難點
128         {
129             Random rand = new Random();// 實例化一個隨機數類的對象
130             int size = rand.nextInt(50);// 隨機決定要畫的點數
131             x2 = e.getX() + 7;
132             y2 = e.getY() + 183;
133             for (int j = 0; j < size; j++) {
134                 // 在0-7之間可以取50次
135                 int x = rand.nextInt(10);
136                 int y = rand.nextInt(10);
137                 // 不斷改變(x1,y1)的坐標值,實現在(x1,y1)的周圍畫點
138                 Shape s = new Shape(x2 + x, y2 + y, x2 + x, y2 + y, width, color, type, i, dm, text);
139                 s.draw(g);
140                 list.add(s);
141                 x1 = x2;
142                 y1 = y2;
143             }
144         }
145     }

  仔細看看代碼,你也許注意到了,我在畫圖時創建了一個Shape對象,並且還把Shape對象存到了一個List中,為什么要這么做?你們可以去別人的博客上貼一個粗略實現的畫圖板代碼,畫幾條直線然后再改變窗體的大小試試看,是不是畫的直線不見了?那要怎么做才能使這些圖形保存下來呢?這就需要用到重繪了。

 

  但是,我們需要知道,為什么圖形會消失?其實計算機中的界面什么都是畫出來的。自然組件也是畫出來的,而改變組件大小的時候,原來的組件無法滿足現在組件的顯示要求,所以組件要重新畫一次,然而此時組件上的圖形並不會重新再畫一次,為什么?組件已經默認有重繪的方法了paint(Graphics g),所以我們需要重寫這個方法,但是我們怎么能讓計算機知道之前畫了什么呢?這是就需要把每次畫的內容記錄到隊列或數組中,重繪時就可以根據這個隊列或是數組進行了。而創建Shape對象自然是為了方便保存這些圖形的數據了。

下面是Shape的寫法

 1 public class Shape {
 2 
 3     private int x1, y1, x2, y2, width;
 4     private Color color;
 5     private String type;
 6     private ImageIcon i;
 7     private DrawMain dm;
 8     private JTextField text;
 9 
10     public Shape(int x1, int y1, int x2, int y2, int width, Color color, String type, ImageIcon i, DrawMain dm,
11             JTextField text) {
12         this.x1 = x1;
13         this.y1 = y1;
14         this.x2 = x2;
15         this.y2 = y2;
16         this.width = width;
17         this.color = color;
18         this.type = type;
19         this.i = i;
20         this.dm = dm;
21         this.text = text;
22     }
23 
24 
25     public void draw(Graphics2D g) {
26         g.setColor(color);
27         g.setStroke(new BasicStroke(width));
28         if (type.equals("Line") || type.equals("Pencil") || type.equals("iso_Tri") || type.equals("Polygon")
29                 || type.equals("Erase") || type.equals("噴槍")) {
30             g.drawLine(x1, y1, x2, y2);
31         } else if (type.equals("Oval")) {
32             g.fillOval(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1));
33         } else if (type.equals("Rect")) {
34             g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1));
35         } else if (type.equals("RoundRect")) {
36             g.drawRoundRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1),
37                     Math.abs(x2 - x1) / 3, Math.abs(y2 - y1) / 3);
38         } else if (type.equals("fill3DRect")) {
39             g.fill3DRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1), true);
40         } else if (type.equals("fillArc")) {
41             double r = ((x2 - x1) * (x2 - x1) + y1 * y1) / (2 * y1);
42             double m = Math.asin((double) (x2 - x1) / r);
43             g.fillArc(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), (int) r, 0, (int) (m * 180 / Math.PI));
44         } else if (type.equals("Image")) {
45             g.drawImage(i.getImage(), Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1), dm);
46         } else if (type.equals("Text")) {
47             g.drawString(text.getText(), x1, y1);
48         }
49     }
50 
51 }

現在還有一個問題,paint該寫在哪?寫在之前寫的DrawMain中

private List<Shape> list = new ArrayList<Shape>();

    public void paint(Graphics gr) {
        super.paint(gr);
        Graphics2D g = (Graphics2D) gr;
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        for (int i = 0; i < list.size(); i++) {
            Shape shape = list.get(i);
            shape.draw(g);
        }
    }

提醒一下:別忘了把事件監聽添加到組件中!!!!

這樣一來,我們的畫圖板就能完美使用了。當然這個畫圖板跟系統中的比起來還是差了很多了,比如撤銷、重做、保存等功能都還不具備,剩下的功能就需要后面慢慢研究再完善了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM