高手写的一篇文章:
Who calls paintComponent
When you subclass JComponent
or JPanel
to draw graphics, override the paintComponent()
method. This method is called because the user did something with the user interface that required redrawing, or your code has explicitly requested that it be redrawn.
Called automatically when it becomes visible
When a window becomes visible (uncovered or deminimized) or is resized, the "system" automatically calls the paintComponent()
method for all areas of the screen that have to be redrawn.
Called indirectly from a user-defined listener via repaint()
When a listener (mouse, button, keyboard, ...) of yours is called, the listener code often makes changes that should be displayed in your graphics area. Never call paintComponent()
method directly.
- Change instance variables. The listener code should set instance variables that
paintComponent()
uses in drawing the panel. After changing the values, the next timepaintComponent()
is called, these new values will be used. But you won't want to wait for a call topaintComponent()
, callrepaint()
. - Call
repaint()
. Therepaint()
method consolidates all requests to change the component (there may be several repaint requests between screen refreshes). It adds an update request to the GUI event queue so that the update will be properly coordinated with other GUI actions (Swing and AWT are not thread-safe). This update request, when processed, callsupdate()
, which callspaint()
, which calls yourpaintComponent()
method (as well as callingpaintBorder()
andpaintChildren()
.
http://www.leepoint.net/notes-java/GUI-lowlevel/graphics/15who-calls-paintcomponent.html
import java.awt.*; import java.awt.event.*; public class DrawLine { Frame f= new Frame("IT资讯交流网"); public static void main(String [] args) { new DrawLine().init(); } public void init() { f.setSize(300,300); f.setVisible(true); f.addMouseListener(new MouseAdapter() { int orgX; int orgY; public void mousePressed(MouseEvent e) { orgX=e.getX(); orgY=e.getY(); } public void mouseReleased(MouseEvent e) { f.getGraphics().setColor(Color.red); //设置绘图颜色为红色 f.getGraphics().drawLine(orgX,orgY,e.getX(),e.getY()); } }); } }
当窗口改变大小后原来画的内容全都不能显示了。
awt线程在重新绘制组件后,会立即调用组件的paint方法,所以我们的图形重绘代码应在paint中编写
public void paint(Graphics g)
可见,awt线程已经获得了组件的Graphics对象,并将它传递给了paint方法,在paint方法中绘图时只能使用这个graphics对象。
当我们想要执行paint方法中的程序代码时,应用程序不应该直接调用paint方法,如果我们想要执行paint中的代码,需调用
component.repaint方法,repaint调用component.update方法,update再调用paint方法。
由于我们不可能直接进入某个组件的paint方法中修改程序代码,我们需要定义一个继承了该组件的子类,在子类中覆盖paint方法,在新的paint方法中编写代码,并将原先创建的组件对象改为由这个子类创建,就可以达到我们的目的了,
import java.awt.Color; import java.awt.Frame; import java.awt.Graphics; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; public class DrawLine extends Frame { int orgX; int orgY; int endX; int endY; public static void main(String [] args) { //new DrawLine().init(); DrawLine dl=new DrawLine(); dl.init(); } public void paint(Graphics g) { g.drawLine(orgX, orgY,endX,endY); } public void init() { setSize(300,300); setVisible(true); addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { orgX=e.getX(); orgY=e.getY(); } public void mouseReleased(MouseEvent e) { endX=e.getX(); endY=e.getY(); Graphics g=getGraphics(); g.setColor(Color.red); g.drawLine(orgX,orgY,e.getX(),e.getY()); } }); } }
上面的程序只能重绘最后一次划线。 要想完全重绘窗口上的内容,需要将每一条直线的坐标保存到一个集合类 中。
另一篇文章:
在Java游戏编程时,使用Swing组件绘图时,一般需要覆盖组件的paintComponent(Graphics)方法,在该方法中写绘图代码,需要注意的是,在绘图代码之前要调用super.paintComponent(g)来清除一个遮光部件的背景。(某些人为图简单省略掉,不要不写)。
此外,如果需要重画,则使用repaint方法,repaint方法会自动调用paintComponent(Graphics)方法。
Java游戏编程中,绘制圆的代码写在Jpanel类的paintComponent(Graphics)方法中,然后在多线程中不断调用repaint方法,从而不断调用paintComponent(Graphics)方法绘出移动的圆形。
如果是在AWT组件内绘图,比如Frame,则需要把绘图代码写在paint(Graphics)方法中。如果需要不断重画,则需要在多线程中调用repaint方法,repaint会自动调用update方法,update方法会自动调用paint方法完成重画。
Java游戏编程中还有一点需要注意:在Swing中绘图,Java提供了双缓冲的功能,而AWT中绘图则没有双缓冲的功能,从而绘图会出现闪烁的问题。