在jdk1.6的API中,有这样一段描述:---javax.swing 类 JComponent:
---从类 java.awt.Component 继承的方法repaint()
API描述:repaint
public void repaint()重绘此组件。 
如果此组件是轻量级组件,则此方法会尽快调用此组件的 paint 方法。否则此方法会尽快调用此组件的 update 方法。
现在,请先看我的代码,随后我讲说明我的问题:
假定BounceFrame、Ball、BallComponent、Bounce这4个类public class Bounce {//这是执行入口
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable(){
public void run(){
JFrame frame = new BounceFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}public class BounceFrame extends JFrame {
private final static long serialVersionUID = 2L;
public BounceFrame()
{
setTitle("Bounce");
setSize(Default_WIDTH,Default_HEIGHT);
comp = new BallComponent();
add(comp, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();
addButton(buttonPanel , "Start" , new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
addBall();
}
});
addButton(buttonPanel , "Close" , new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
add(buttonPanel , BorderLayout.SOUTH);
}
private void addButton(Container c, String title, final ActionListener listener)
{
JButton button = new JButton(title);
c.add(button);
button.addActionListener(listener);
}
private void addBall()
{
try{
Ball ball = new Ball();
comp.add(ball);//这一步是添加并且重绘一个球
for(int i=0 ; i <= STEPS ; i++ )
{
ball.move(comp.getBounds());
// comp.paint(comp.getGraphics());
comp.repaint(); //此时不执行移动重绘,这就是问题点
// comp.update(comp.getGraphics());
Thread.sleep(DELAY);
}
}catch(InterruptedException err){}
}
private BallComponent comp ;
private final static int Default_WIDTH = 450;
private final static int Default_HEIGHT = 300;
private final static int STEPS = 1000;
private final static int DELAY = 3;
}public class Ball {
public void move(Rectangle2D bounds)
{
x += dx ;
y += dy ;
if( x < bounds.getMinX())
{
x = bounds.getMinX();
dx = -dx ;
}
if( x + XSIZE >= bounds.getMaxX())
{
x = bounds.getMaxX() - XSIZE ;
dx = -dx ;
}
if( y < bounds.getMinY())
{
y = bounds.getMinY();
dy = -dy ;
}
if( y + YSIZE >= bounds.getMaxY())
{
y = bounds.getMaxY() - YSIZE ;
dy = -dy ;
}
}
public Ellipse2D getShape()//把这个传给BallComponent,让BallComponent来绘制圆
{
return new Ellipse2D.Double(x, y, XSIZE, YSIZE);
}
private final static int XSIZE = 15 ;
private final static int YSIZE = 15 ;
private static double x = 0 ;
private static double y = 0 ;
private double dx = 1 ;
private double dy = 1 ;
}
public class BallComponent extends JPanel{
private final static long serialVersionUID = 1L;
public void add(Ball b)
{
balls.add(b);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g ;
for(Ball b : balls)
{
g2.fill(b.getShape());
}
}
private ArrayList<Ball> balls = new ArrayList<Ball>();
}
这,是我完整的代码,我全部贴上 !问题:
请看BounceFrame类,这里面有一个comp调用了重绘方法,
请注意,我这里用了三种重绘方法[注释了2种]。
这3中方法中,为什么comp.reapint()就没办法使得 圆球 运动,别的两个就可以 ?

解决方案 »

  1.   

    看了下JDK中的源码,大致是这样,update里其实也是调的paint方法,也就是你说的两个行的方法是一样的,另一个是rapaint 下面是jdk中源码: public void repaint() {
            repaint(0, 0, 0, width, height);
        }
     public void repaint(long tm, int x, int y, int width, int height) {
            if (this.peer instanceof LightweightPeer) {
                // Needs to be translated to parent coordinates since
                // a parent native container provides the actual repaint
                // services.  Additionally, the request is restricted to
                // the bounds of the component.
                if (parent != null) {
                    int px = this.x + ((x < 0) ? 0 : x);
                    int py = this.y + ((y < 0) ? 0 : y);
                    int pwidth = (width > this.width) ? this.width : width;
                    int pheight = (height > this.height) ? this.height : height;
                    parent.repaint(tm, px, py, pwidth, pheight);
                }
            } else {
                if (isVisible() && (this.peer != null) &&
                    (width > 0) && (height > 0)) {
                    PaintEvent e = new PaintEvent(this, PaintEvent.UPDATE,
                                                  new Rectangle(x, y, width, height));
                    Toolkit.getEventQueue().postEvent(e);           
                }
            }
        }
    这里有个 PaintEvent ,应该只是个事件,GUI只是添加了这一事件,而这事件应该不是立即触发,应该有其它什么的告诉它触发才有起作用。
      

  2.   

    怎么讲呢? 源码里面,有一个进入if的parent.repaint(tm, px, py, pwidth, pheight);调用,只是在else才Toolkit.getEventQueue().postEvent(e)派送这个PaintEvent事件。当然,这个跟我的问题的确相关,但到底哪里相关呢? 我不太清楚,望指教!现在想知道的就在这里!
      

  3.   


    引用 1 楼 tlfu_12344 的回复:
    看了下JDK中的源码..........
     怎么讲呢? 源码里面,有一个进入if的parent.repaint(tm, px, py, pwidth, pheight);调用,只是在else才Toolkit.getEventQueue().postEvent(e)派送这个PaintEvent事件。
     
    当然,这个跟我的问题的确相关,但到底哪里相关呢? 我不太清楚,望指教!
     
    现在想知道的就在这里! parent调有还是调这个方法嘛,就是直到没parent为止,最终还是会执行else也就是那事件
      

  4.   


    先说下吧,我"重修"下多线程,再看CoreJava的时候,碰到的这个问题,
    CoreJava书上只是很随意的说了句:“由于addBall()掌握了控制权,所以comp.repaint()无效。”所以采用了comp.paint(comp.getGraphics())。
    这是多线程第一个代码,我在好奇之下敲了这个代码,果然直接comp.repaint()这种形式是不行的。
    只是很奇怪why?所以,想搞懂3点:
    1、为什么这个代码中repaint()不行而paint(Graphics g)可以 【也就是提问的问题】
    2、paint和repaint()到底有什么区别 ?
    3、paint和repaint()这两个函数之间用法的不同处在哪里 ???提前谢谢 ! 我这个菜鸟 述 .......  
      

  5.   

    这里应该就是我上面所说的应该有什么触发此事件了,这个什么触发这个肯定是有什么规则的,要不你看的书上也不会说什么掌控权了,至于是什么规则应该了解GUI工作原理有关了,毕竟我不是java这块的,LZ可以自己看GUI原理相关的,个人坚信肯定是有什么规则的。至于方法区别看源码嘛
      

  6.   

    java画图没怎么用过,也是门外汉那!LZ的疑惑是不是repaint只走了一个分支,没走另外一个是把?
    可以看看this.peer这个属性,是如何修改的,把它改成另外一个分支符合的条件试试呗?
      

  7.   


    果然 ... 其实我也刚学学完SSH...
      

  8.   


    我的疑惑的确在于repaint只走了一个分支 ...戳中要点了 ... 
      

  9.   


    我的疑惑的确在于repaint只走了一个分支 ...戳中要点了 ... 
    没接触过不能乱讲,只能给点解决问题的方法。不妨跟下源码,看看那个判断条件如何改变?
      

  10.   


    我的疑惑的确在于repaint只走了一个分支 ...戳中要点了 ... 
    没接触过不能乱讲,只能给点解决问题的方法。不妨跟下源码,看看那个判断条件如何改变?恩 。
    跟了,不过 ... 看不懂源码 ...