首先看两段类似的程序
单线程的
/** */
/**
* @(#)Bounce.java
*
*
* @author livahu
* @version 1.00 2006/10/16
*/
import
java.awt.
*
;
import
java.awt.event.
*
;
import
java.awt.geom.
*
;
import
java.util.
*
;
import
javax.swing.
*
;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
public
class
Bounce
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public Bounce() ...{
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public static void main(String[] args) ...{
JFrame frame = new BounceFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
class
Ball
...
{
private static final int XSIZE = 15;
private static final int YSIZE = 15;
private double x = 0;
private double y = 0;
private double dx = 1;
private double dy = 1;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void move(Rectangle2D bounds) ...{
x += dx;
y += dy;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if (x < bounds.getMinX()) ...{
x = bounds.getMinX();
dx = -dx;
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if (x + XSIZE >= bounds.getMaxX()) ...{
x = bounds.getMaxX() - XSIZE;
dx = -dx;
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if (y < bounds.getMinY()) ...{
y = bounds.getMinY();
dy = -dy;
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if (y + YSIZE >= bounds.getMaxY()) ...{
y = bounds.getMaxY() - YSIZE;
dy = -dy;
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public Ellipse2D getShape() ...{
return new Ellipse2D.Double(x, y, XSIZE, YSIZE);
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
class
BallPanel
extends
JPanel
...
{
private ArrayList<Ball> balls = new ArrayList<Ball>();
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void add(Ball b) ...{
balls.add(b);
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void remove(Ball b) ...{
balls.remove(b);
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void paintComponent(Graphics g) ...{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
for (Ball b : balls) ...{
g2.fill(b.getShape());
}
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
class
BounceFrame
extends
JFrame
...
{
private BallPanel panel;
public static final int DEFAULT_WIDTH = 450;
public static final int DEFAULT_HEIGHT = 350;
public static final int STEPS = 1000;
public static final int DELAY = 3;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public BounceFrame() ...{
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
setTitle("Bounce");
panel = new BallPanel();
add(panel, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();
addButton(buttonPanel, "Start",
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
new ActionListener() ...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void actionPerformed(ActionEvent event) ...{
addBall();
}
});
addButton(buttonPanel, "Close",
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
new ActionListener() ...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void actionPerformed(ActionEvent event) ...{
System.exit(0);
}
});
add(buttonPanel, BorderLayout.SOUTH);
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void addButton(Container c, String title, ActionListener listener) ...{
JButton button = new JButton(title);
c.add(button);
button.addActionListener(listener);
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void addBall() ...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
try ...{
Ball ball = new Ball();
panel.add(ball);
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
for (int i = 1; i <= STEPS; i++) ...{
ball.move(panel.getBounds());
panel.paint(panel.getGraphics());
// panel.repaint(); 为什么不能使用repaint?使用repaint屏幕上没有任何球。repaint 和 paint有什么区别与关系
Thread.sleep(DELAY);
}
panel.remove(ball);
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
} catch(InterruptedException ex) ...{
}
}
}
多线程的
/** */
/**
* @(#)Bounce.java
*
*
* @author livahu
* @version 1.00 2006/10/16
*/
import
java.awt.
*
;
import
java.awt.event.
*
;
import
java.awt.geom.
*
;
import
java.util.
*
;
import
javax.swing.
*
;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
public
class
BounceThread
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public BounceThread() ...{
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public static void main(String[] args) ...{
JFrame frame = new BounceFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
class
BallRunnable
implements
Runnable
...
{
private Ball ball;
private BallPanel panel;
public static final int STEPS = 1000;
public static final int DELAY = 5;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public BallRunnable(Ball aBall, BallPanel panel) ...{
ball = aBall;
this.panel = panel;
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void run() ...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
try ...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
for (int i = 1; i <= STEPS; i++) ...{
ball.move(panel.getBounds());
panel.repaint();//这里又可以用repaint
Thread.sleep(DELAY);
}
panel.remove(ball);
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
} catch(InterruptedException ex) ...{
}
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
class
Ball
...
{
private static final int XSIZE = 15;
private static final int YSIZE = 15;
private double x = 0;
private double y = 0;
private double dx = 1;
private double dy = 1;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void move(Rectangle2D bounds) ...{
x += dx;
y += dy;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if (x < bounds.getMinX()) ...{
x = bounds.getMinX();
dx = -dx;
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if (x + XSIZE >= bounds.getMaxX()) ...{
x = bounds.getMaxX() - XSIZE;
dx = -dx;
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if (y < bounds.getMinY()) ...{
y = bounds.getMinY();
dy = -dy;
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if (y + YSIZE >= bounds.getMaxY()) ...{
y = bounds.getMaxY() - YSIZE;
dy = -dy;
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public Ellipse2D getShape() ...{
return new Ellipse2D.Double(x, y, XSIZE, YSIZE);
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
class
BallPanel
extends
JPanel
...
{
private ArrayList<Ball> balls = new ArrayList<Ball>();
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void add(Ball b) ...{
balls.add(b);
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void remove(Ball b) ...{
balls.remove(b);
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void paintComponent(Graphics g) ...{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
for (Ball b : balls) ...{
g2.fill(b.getShape());
}
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
class
BounceFrame
extends
JFrame
...
{
private BallPanel panel;
public static final int DEFAULT_WIDTH = 450;
public static final int DEFAULT_HEIGHT = 350;
public static final int STEPS = 1000;
public static final int DELAY = 3;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public BounceFrame() ...{
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
setTitle("Bounce");
panel = new BallPanel();
add(panel, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();
addButton(buttonPanel, "Start",
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
new ActionListener() ...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void actionPerformed(ActionEvent event) ...{
addBall();
}
});
addButton(buttonPanel, "Close",
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
new ActionListener() ...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void actionPerformed(ActionEvent event) ...{
System.exit(0);
}
});
add(buttonPanel, BorderLayout.SOUTH);
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void addButton(Container c, String title, ActionListener listener) ...{
JButton button = new JButton(title);
c.add(button);
button.addActionListener(listener);
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void addBall() ...{
Ball b = new Ball();
panel.add(b);
Runnable r = new BallRunnable(b, panel);
Thread t = new Thread(r);
t.start();
}
}
从这两段程序,不难发现,本因调用repaint的单线程程序无法重绘图象,但在多线程里就没有一点问题。那repaint和paint在线程上有什么区别类?我想了很久,最后感谢zxyxc的帮助,让我知道了事件分配的一些细节。
是这样的:Java中事件的分配调度是由专门的线程完成的。当调用repaint方法时,实际上是发送一个重绘事件到事件队列,而后事件分配线程会调用paint方法来完成重绘。当在多线程时,一切正常,因为是调用的repaint方法的线程没有占据全部的CPU时间,所以事件分配线程可以执行,并调用paint完成重绘。
而在单线程情况下,由于主线程完全占据了CPU,事件分配线程无法执行,自然也就没办法去分配通过调用repaint方法插入的重绘事件。取代的做法就是直接调用paint(),而不是等待事件分配线程去调用。