JAVA图形编程Swing之——JPanel绘图

JAVA图形编程Swing之——JPanel绘图

 

    一直搞不清怎么在JPanel中绘2D图像,主要是不知怎样得到Graphics类的对像来画图,今天查了查资料,测试N种方法,终于搞明白。下面做一个测试总结。

 

     一、自定义一个类,继承JPanel,直接重写它的paint方法。

1. /** 
2.  * 定义一个继承自JPanel的类,重写它的paint方法 * 
3.  */  
4. class MyPanel extends JPanel  
5. {  
6. private int x = 200;  
7. private int y = 200;  
8.       
9. public void display()  
10.     {  
11.         x ++;  
12.         y ++;  
13.           
14. //重绘JPanel  
15. this.repaint();  
16.     }  
17.       
18. /** 
19.      * repaint方法会调用paint方法,并自动获得Graphics对像 
20.      * 然后可以用该对像进行2D画图 
21.      * 注:该方法是重写了JPanel的paint方法 
22.      */  
23. public void paint(Graphics g)  
24.     {  
25. //调用的super.paint(g),让父类做一些事前的工作,如刷新屏幕  
26. super.paint(g);   
27.         Graphics2D g2d = (Graphics2D)g;  
28.           
29. //设置画图的颜色  
30. 100, 100, true);//填充一个矩形         
31.     }  
32. }  
33.   
34. public class PanelTest  
35. {  
36. public static void main(String[] args)  
37.     {  
38. new JFrame();  
39. new MyPanel();  
40.           
41. 200, 200, 500, 500);  
42.         jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
43.         jf.add(jp);  
44. true);  
45.           
46. while(true)  
47.         {  
48. //不停的重绘JPanel,实现动画的效果  
49.             jp.display();  
50.               
51. try  
52.             {  
53. 300);  
54.             }  
55. catch (InterruptedException e)  
56.             {  
57.                 e.printStackTrace();  
58.             }  
59.         }  
60.     }  
61. }

 

    二、图像缓冲

 

    第二种方法就是使用Image和BufferImage技术,预先在一个图形缓冲中绘好要显示的内容,然后在paint方法中,一次性的把图形缓冲刷新到JPanel里肌,这种方法涉及到AWT中的Image和BufferImage,前者是一个接口,后者是一个可以实例化的类。其实,JPanel也是继承自AWT的Component类,该类有一个方法:Image createImage(int width, int height) ,这个方法也常在继承自JPanel的类中用于创建一幅用于双缓冲的、可在屏幕外绘制的图像。

    实现方法一:

1. /** 
2.  * 定义一个继承自JPanel的类,重写它的paint方法 * 
3.  */  
4. class MyPanel1 extends JPanel  
5. {  
6. private int x = 200;  
7. private int y = 200;  
8. private Image image;    //图像缓冲  
9. private Graphics og;  
10.       
11. public void display()  
12.     {  
13.         x ++;  
14.         y ++;  
15.           
16. if(og == null)  
17.         {  
18. //JPanel继承自Component类,可以使用它的方法createImage创建一幅和JPanel大小相同的图形缓冲  
19. //然后用它Image接口的方法获得绘图对像  
20. this.createImage(this.getWidth(),this.getHeight());  
21. if(image != null)og = image.getGraphics();  
22.         }  
23.           
24. if(og != null)  
25.         {  
26. //调用的super.paint(g),让父类做一些事前的工作,如刷新屏幕  
27. super.paint(og);      
28.                           
29. //设置画图的颜色  
30. 100, 100, true);//绘图                  
31. //this.paint(this.getGraphics());  
32.         }  
33. //重绘JPanel  
34. this.repaint();  
35.     }  
36.       
37. /** 
38.      * repaint方法会调用paint方法,并自动获得Graphics对像 
39.      * 然后可以用该对像进行2D画图 
40.      * 注:该方法是重写了JPanel的paint方法 
41.      */  
42. public void paint(Graphics g)  
43.     {  
44. 0, 0, this);   
45.     }  
46. }  
47.   
48. public class PanelTest2  
49. {  
50. public static void main(String[] args)  
51.     {  
52. new JFrame();  
53. new MyPanel1();  
54.           
55. 200, 200, 500, 500);  
56.         jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
57.         jf.add(jp);  
58. true);  
59.           
60. while(true)  
61.         {  
62. //不停的重绘JPanel,实现动画的效果  
63.             jp.display();  
64.               
65. try  
66.             {  
67. 300);  
68.             }  
69. catch (InterruptedException e)  
70.             {  
71.                 e.printStackTrace();  
72.             }  
73.         }  
74.     }  
75. }

    

    实现方法二:

1. class MyPanel3 extends JPanel  
2. {  
3. private int x = 200;  
4. private int y = 200;  
5.       
6. private Graphics g;  
7. private Image im ;  
8.       
9. //构造方法,获得外部Image对像的引用  
10. public MyPanel3(Image im)  
11.     {  
12. if(im != null)  
13.         {  
14. this.im = im;  
15.             g = im.getGraphics();  
16.         }  
17.     }  
18.       
19. public void display()  
20.     {  
21.         x ++;  
22.         y ++;             
23. if(g != null)  
24.         {  
25. //调用的super.paint(g),让父类做一些事前的工作,如刷新屏幕  
26. super.paint(g);  
27. //设置画图的颜色  
28. 100, 100, true); //填充一个矩形          
29. //更新缓图  
30. this.repaint();  
31.         }  
32.     }  
33.       
34. /** 
35.      * repaint方法会调用paint方法,并自动获得Graphics对像 
36.      * 然后可以用该对像进行2D画图 
37.      * 注:该方法是重写了JPanel的paint方法 
38.      */  
39. public void paint(Graphics g)  
40.     {  
41. 0, 0, this);  
42.     }  
43. }  
44.   
45. public class PanelTEST4  
46. {  
47. public static void main(String[] args)  
48.     {  
49. //在自定义Panel的外部定义一个Image绘图区  
50. new BufferedImage(500,500,BufferedImage.TYPE_INT_RGB);  
51.           
52. new JFrame();  
53. //通过构造方法将缓冲缓冲区对像的引用传给自定义Panel  
54. new MyPanel3(im);  
55.           
56. 200,200,500, 500);  
57. 300, 300);  
58.         jf.add(jp);  
59.         jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);            
60. true);  
61.       
62. while(true)  
63.         {  
64.             jp.display();  
65.               
66. try  
67.             {  
68. 300);  
69.             }   
70. catch (InterruptedException e)  
71.             {  
72.                 e.printStackTrace();  
73.             }  
74.         }         
75.     }  
76. }


    总结:在绘制2D图形和实现动画的效果时,要用到AWT中的绘图技术和缓冲技术,如果只是简单的绘图,那么自定义Panel类,重写Paint方法,把要绘图代码放到paint方法中,由系统自动调用paint方法即可。

    要实现动画效果则就要定时的调用repaint方法,repaint方法则会调用paint方法实现Panel重绘。

 

    JPanel在什么情况下会被重绘呢?

    1. 在repaint方法被显式的调用时。

    2. 在窗口最小化然后又被显示时。

    3. 在窗口被拉伸时。