论文部分内容阅读
摘要:在进行Java GUI编程时,程序利用paint(Graphics g)方法来实现组件的绘制;然而Java的绘图机制是怎样的,paint方法又是何时调用、如何调用,且每次调用时paint方法的执行次数是怎样的?轻量级和重量级组件调用paint有哪些区别等,本文作者将针对这些问题,用案例分析的方法来一一解答。
关键词:绘图机制;paint;调用
学过Java程序设计语言的朋友都知道,在学习Java GUI编程时,我们都知道paint方法是用来绘制图形的。有了paint方法,我们可以在Java中绘制各种漂亮的组件,或开发漂亮炫酷的游戏。但是paint是如何调用的?程序启动时,paint方法执行了一次还是多次,原理是什么?另外Swing组件和AWT组件对super.paint方法是如何相应的,组件在处理动画时,对KeyListner又是如何响应的呢?关于这些细节性的问题,许多初学者总是模棱两可。笔者经过查找资料,并写程序进行验证,得出一些结果,以供分享。
问题1:Java的绘图机制是怎样的?
AWT是使用回调机制来处理绘画的,并且这种机制对轻量级和重量级组件相同。也就是说我们需要把渲染组件的代码写在一个可覆盖的特殊的方法中,这个方法是public void paint(Graphics g);其中 Graphics是图形上下文对象,用来完成具体的绘制工作。paint方法由AWT框架调用或者由程序自身通过repaint方法来调用。
问题2:画图时,paint是何时调用,如何调用,调用几次的问题。
Java绘图时,用到的paint方法继承自AWT中的Component方法,该方法在对象加载时自动调用,用来绘制该组件内部的所有图形图像。使用repaint()方法,可以再次调用paint方法,实现组件的重绘。但是paint方法是什么时候开始执行,执行了几次呢?下面我们用例子,来加以分析。
public class Test extends Applet//引入包的代码省略
{Image img = null;int t =0;
public void init(){System.out.print("初始化====");
img = getImage(getCodeBase(),"1.jpg");}
public void paint(Graphics g)
{t++;System.out.print("我是paint===="+t+"");
g.fillRect(50,50,80,80);//代码段1,绘制矩形
// g.drawImage(img,50,50,this); //代碼段2,绘制图形}}
执行代码段1的结果:
初始化====我是paint====1
执行代码段2的结果:
初始化====我是paint====1我是paint====2……我是paint====47
从上面结果可以发现,启动浏览器时,系统自动调用init()方法进行程序初始化,接着系统自动找到paint()方法对图像进行绘制。而且paint()方法调用的次数,跟绘制的内容有关,图形简单时,可能执行一次,图像复杂时,可能会自动调用很多次,直到图形图像完全绘制成功。另外还有当组件大小发生改变,或组件有坏点(damage)需要被修复时,系统都会自发地调用repaint方法,进行组件的重绘。
问题3:Java程序绘图时,JPanel和Panel对super.paint()的响应问题。
Java通过调用paint()方法来绘制组件,但是 AWT框架中轻量级组件与重量级组件实现代码还是有区别的。
轻量级组件的绘制依赖与包含关系阶层中的重量级祖先组件,当这个祖先组件被通知绘制时,它将把绘制请求转化为绘制自身上任何可见的子孙组件,这个方法是由java.awt.Container中的 paint() 方法来完成的,因此任何Container的子类,在覆盖paint方法时一定要记得调用super.paint()来保证,它上面的轻量级子孙组件都被绘制到了。代码可以这样来完成:
public class MyContainer extends Container {
public void paint(Graphics g) { // 先绘制自身内容, 然后确保轻量级子组件被绘制
super.paint(g);}}
下面我们将通过案例,来观察:
class myPanel extends JPanel implements KeyListener //重要代码:继承JPanel/Panel
{int x=50;public myPanel(){addKeyListener(this);} //为面板增加键盘监听器
public void paint(Graphics g){super.paint(g);//重要代码段:super.paint
g.setColor(Color.orange); g.fillRect(x, 50, 60, 60);}//设置画笔颜色,填充矩形
public void keyPressed(KeyEvent e){x=x+10;repaint();//释放键盘,矩形向右移动10像素;}
public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e){}}
创建myPanel对象p,设置背景色为青色,同时在面板p上添加标签“测试super.paint()”,程序将出现四种情况,对应3种效果。
(1)面板继承JPanel,且paint方法中调用super.paint(),所得结果如图2。
(2)面板继承JPanel,且paint方法中没有调用super.paint(),所得结果如图1。
(3)面板继承Panel,且paint方法中没有调用super.paint(),所得结果如图3。
(4)面板继承Panel,且paint方法中调用super.paint(),所得结果如图2。
问题4:处理动画时,JPanel和JApplet等Swing组件对KeyListner无响应的问题。
为面板增加键盘监听器KeyListner,若面板继承java.awt.Panel,那么当程序运行时,每敲击一次键盘,上述案例中的矩形方块开始向右移动10个像素的距离;但是若面板继承javax.swing.JPanel,敲击键盘,则无任何相应动作。这又是什么原因引起的呢?
经过实验分析,笔者发现JPanel等Swing组件在渲染完成后,无法获取focus,所以我们只需要上层容器setvisible(true)之前,先设置 p.requestFocus();为面板对象获取焦点即可。
以上分析,希望对爱好Java GUI编程的学习者提供帮助。
关键词:绘图机制;paint;调用
学过Java程序设计语言的朋友都知道,在学习Java GUI编程时,我们都知道paint方法是用来绘制图形的。有了paint方法,我们可以在Java中绘制各种漂亮的组件,或开发漂亮炫酷的游戏。但是paint是如何调用的?程序启动时,paint方法执行了一次还是多次,原理是什么?另外Swing组件和AWT组件对super.paint方法是如何相应的,组件在处理动画时,对KeyListner又是如何响应的呢?关于这些细节性的问题,许多初学者总是模棱两可。笔者经过查找资料,并写程序进行验证,得出一些结果,以供分享。
问题1:Java的绘图机制是怎样的?
AWT是使用回调机制来处理绘画的,并且这种机制对轻量级和重量级组件相同。也就是说我们需要把渲染组件的代码写在一个可覆盖的特殊的方法中,这个方法是public void paint(Graphics g);其中 Graphics是图形上下文对象,用来完成具体的绘制工作。paint方法由AWT框架调用或者由程序自身通过repaint方法来调用。
问题2:画图时,paint是何时调用,如何调用,调用几次的问题。
Java绘图时,用到的paint方法继承自AWT中的Component方法,该方法在对象加载时自动调用,用来绘制该组件内部的所有图形图像。使用repaint()方法,可以再次调用paint方法,实现组件的重绘。但是paint方法是什么时候开始执行,执行了几次呢?下面我们用例子,来加以分析。
public class Test extends Applet//引入包的代码省略
{Image img = null;int t =0;
public void init(){System.out.print("初始化====");
img = getImage(getCodeBase(),"1.jpg");}
public void paint(Graphics g)
{t++;System.out.print("我是paint===="+t+"");
g.fillRect(50,50,80,80);//代码段1,绘制矩形
// g.drawImage(img,50,50,this); //代碼段2,绘制图形}}
执行代码段1的结果:
初始化====我是paint====1
执行代码段2的结果:
初始化====我是paint====1我是paint====2……我是paint====47
从上面结果可以发现,启动浏览器时,系统自动调用init()方法进行程序初始化,接着系统自动找到paint()方法对图像进行绘制。而且paint()方法调用的次数,跟绘制的内容有关,图形简单时,可能执行一次,图像复杂时,可能会自动调用很多次,直到图形图像完全绘制成功。另外还有当组件大小发生改变,或组件有坏点(damage)需要被修复时,系统都会自发地调用repaint方法,进行组件的重绘。
问题3:Java程序绘图时,JPanel和Panel对super.paint()的响应问题。
Java通过调用paint()方法来绘制组件,但是 AWT框架中轻量级组件与重量级组件实现代码还是有区别的。
轻量级组件的绘制依赖与包含关系阶层中的重量级祖先组件,当这个祖先组件被通知绘制时,它将把绘制请求转化为绘制自身上任何可见的子孙组件,这个方法是由java.awt.Container中的 paint() 方法来完成的,因此任何Container的子类,在覆盖paint方法时一定要记得调用super.paint()来保证,它上面的轻量级子孙组件都被绘制到了。代码可以这样来完成:
public class MyContainer extends Container {
public void paint(Graphics g) { // 先绘制自身内容, 然后确保轻量级子组件被绘制
super.paint(g);}}
下面我们将通过案例,来观察:
class myPanel extends JPanel implements KeyListener //重要代码:继承JPanel/Panel
{int x=50;public myPanel(){addKeyListener(this);} //为面板增加键盘监听器
public void paint(Graphics g){super.paint(g);//重要代码段:super.paint
g.setColor(Color.orange); g.fillRect(x, 50, 60, 60);}//设置画笔颜色,填充矩形
public void keyPressed(KeyEvent e){x=x+10;repaint();//释放键盘,矩形向右移动10像素;}
public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e){}}
创建myPanel对象p,设置背景色为青色,同时在面板p上添加标签“测试super.paint()”,程序将出现四种情况,对应3种效果。
(1)面板继承JPanel,且paint方法中调用super.paint(),所得结果如图2。
(2)面板继承JPanel,且paint方法中没有调用super.paint(),所得结果如图1。
(3)面板继承Panel,且paint方法中没有调用super.paint(),所得结果如图3。
(4)面板继承Panel,且paint方法中调用super.paint(),所得结果如图2。
问题4:处理动画时,JPanel和JApplet等Swing组件对KeyListner无响应的问题。
为面板增加键盘监听器KeyListner,若面板继承java.awt.Panel,那么当程序运行时,每敲击一次键盘,上述案例中的矩形方块开始向右移动10个像素的距离;但是若面板继承javax.swing.JPanel,敲击键盘,则无任何相应动作。这又是什么原因引起的呢?
经过实验分析,笔者发现JPanel等Swing组件在渲染完成后,无法获取focus,所以我们只需要上层容器setvisible(true)之前,先设置 p.requestFocus();为面板对象获取焦点即可。
以上分析,希望对爱好Java GUI编程的学习者提供帮助。