在多线程中可以很方便的控制多个弹跳球的移动,当球体碰到窗体边界便折回。
用Thread.start启动一个新的线程。
1 /** 2 @version 1.32 2004-07-27 3 @author Cay Horstmann 4 */ 5 6 import java.awt.*; 7 import java.awt.event.*; 8 import java.awt.geom.*; 9 import java.util.*; 10 import javax.swing.*; 11 12 /** 13 Shows an animated bouncing ball. 14 */ 15 public class BounceThread 16 { 17 public static void main(String[] args) 18 { 19 JFrame frame = new BounceFrame(); 20 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 21 frame.setVisible(true); 22 } 23 } 24 25 /** 26 A runnable that animates a bouncing ball. 27 */ 28 class BallRunnable implements Runnable 29 { 30 /** 31 Constructs the runnable. 32 @aBall the ball to bounce 33 @aPanel the component in which the ball bounces 34 */ 35 public BallRunnable(Ball aBall, Component aComponent) 36 { 37 ball = aBall; 38 component = aComponent; 39 } 40 41 public void run() 42 { 43 try 44 { 45 for (int i = 1; i <= STEPS; i++) 46 { 47 ball.move(component.getBounds()); 48 component.repaint(); 49 Thread.sleep(DELAY); 50 } 51 } 52 catch (InterruptedException e) 53 { 54 } 55 } 56 57 private Ball ball; 58 private Component component; 59 public static final int STEPS = 1000; 60 public static final int DELAY = 5; 61 } 62 63 /** 64 A ball that moves and bounces off the edges of a 65 rectangle 66 */ 67 class Ball 68 { 69 /** 70 Moves the ball to the next position, reversing direction 71 if it hits one of the edges 72 */ 73 public void move(Rectangle2D bounds) 74 { 75 x += dx; 76 y += dy; 77 if (x < bounds.getMinX()) 78 { 79 x = bounds.getMinX(); 80 dx = -dx; 81 } 82 if (x + XSIZE >= bounds.getMaxX()) 83 { 84 x = bounds.getMaxX() - XSIZE; 85 dx = -dx; 86 } 87 if (y < bounds.getMinY()) 88 { 89 y = bounds.getMinY(); 90 dy = -dy; 91 } 92 if (y + YSIZE >= bounds.getMaxY()) 93 { 94 y = bounds.getMaxY() - YSIZE; 95 dy = -dy; 96 } 97 } 98 99 /** 100 Gets the shape of the ball at its current position. 101 */ 102 public Ellipse2D getShape() 103 { 104 return new Ellipse2D.Double(x, y, XSIZE, YSIZE); 105 } 106 107 private static final int XSIZE = 15; 108 private static final int YSIZE = 15; 109 private double x = 0; 110 private double y = 0; 111 private double dx = 1; 112 private double dy = 1; 113 } 114 115 /** 116 The panel that draws the balls. 117 */ 118 class BallPanel extends JPanel 119 { 120 /** 121 Add a ball to the panel. 122 @param b the ball to add 123 */ 124 public void add(Ball b) 125 { 126 balls.add(b); 127 } 128 129 public void paintComponent(Graphics g) 130 { 131 super.paintComponent(g); 132 Graphics2D g2 = (Graphics2D) g; 133 for (Ball b : balls) 134 { 135 g2.fill(b.getShape()); 136 } 137 } 138 139 private ArrayList<Ball> balls = new ArrayList<Ball>(); 140 } 141 142 /** 143 The frame with panel and buttons. 144 */ 145 class BounceFrame extends JFrame 146 { 147 /** 148 Constructs the frame with the panel for showing the 149 bouncing ball and Start and Close buttons 150 */ 151 public BounceFrame() 152 { 153 setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); 154 setTitle("BounceThread"); 155 156 panel = new BallPanel(); 157 add(panel, BorderLayout.CENTER); 158 JPanel buttonPanel = new JPanel(); 159 addButton(buttonPanel, "Start", 160 new ActionListener() 161 { 162 public void actionPerformed(ActionEvent event) 163 { 164 addBall(); 165 } 166 }); 167 168 addButton(buttonPanel, "Close", 169 new ActionListener() 170 { 171 public void actionPerformed(ActionEvent event) 172 { 173 System.exit(0); 174 } 175 }); 176 add(buttonPanel, BorderLayout.SOUTH); 177 } 178 179 /** 180 Adds a button to a container. 181 @param c the container 182 @param title the button title 183 @param listener the action listener for the button 184 */ 185 public void addButton(Container c, String title, ActionListener listener) 186 { 187 JButton button = new JButton(title); 188 c.add(button); 189 button.addActionListener(listener); 190 } 191 192 /** 193 Adds a bouncing ball to the canvas and starts a thread 194 to make it bounce 195 */ 196 public void addBall() 197 { 198 Ball b = new Ball(); 199 panel.add(b); 200 Runnable r = new BallRunnable(b, panel); 201 Thread t = new Thread(r); 202 t.start(); 203 } 204 205 private BallPanel panel; 206 public static final int DEFAULT_WIDTH = 450; 207 public static final int DEFAULT_HEIGHT = 350; 208 public static final int STEPS = 1000; 209 public static final int DELAY = 3; 210 }