class BallPanel extends JPanel { 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>();
}

for (Ball b : balls)不是循环输出balls中的内容吗,为什么 每次只输出一次完整的代码是出自java核心技术 卷二
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import javax.swing.*;public class BounceThread {
public static void main(String[] args) {
JFrame frame = new BounceFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}class BallRunnable implements Runnable { public BallRunnable(Ball aBall, Component aComponent) {
ball = aBall;
component = aComponent;
} public void run() {
try {
for (int i = 1; i <= STEPS; i++) {
ball.move(component.getBounds());
component.repaint();
Thread.sleep(DELAY);
}
} catch (InterruptedException e) {
}
} private Ball ball;
private Component component;
public static final int STEPS = 1000;
public static final int DELAY = 5050;
}class Ball {
// 这块就是碰到 边缘就弹回来的地方的坐标
public void move(Rectangle2D bounds) { y += dy;
x += dx; 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() {
return new Ellipse2D.Double(x, y, XSIZE, YSIZE);
} private static final int XSIZE = 50;
private static final int YSIZE = 50;
private double x = 0;
private double y = 0;
private double dx = 10;
private double dy = 30;
}class BallPanel extends JPanel { 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>();
}class BounceFrame extends JFrame { public BounceFrame() {
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
setTitle("BounceThread"); panel = new BallPanel();
add(panel, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();
addButton(buttonPanel, "Start", new ActionListener() {
public void actionPerformed(ActionEvent event) {
addBall();
}
});
addButton(buttonPanel, "Close", new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
});
add(buttonPanel, BorderLayout.SOUTH);
} public void addButton(Container c, String title, ActionListener listener) {
JButton button = new JButton(title);
c.add(button);
button.addActionListener(listener);
} public void addBall() {
Ball b = new Ball();
panel.add(b);
Runnable r = new BallRunnable(b, panel);
Thread t = new Thread(r);
t.start();
} private BallPanel panel;
public static final int DEFAULT_WIDTH = 900;
public static final int DEFAULT_HEIGHT = 750;
public static final int STEPS = 1000;
public static final int DELAY = 1000;
}

解决方案 »

  1.   

    你看看,balls 的值是好多。debug 一下
      

  2.   

    for (Ball b : balls) {
    g2.fill(b.getShape());
    我想知道 ,这段代码具体是怎么实现 的、、
      

  3.   

    for(Ball b : balls)
    foreach语法,遍历balls中每一个元素并且赋值给b
      

  4.   


    哪里可以看出for (Ball b : balls)每次只输出一次?
    除非ballls的size为1。对于你的第二个问题:for(Ball b : balls)循环是怎么实现的,你可以去看下JVM的源码了。
    这种循环是Java 5.0后出现的,
    你问这个问题,相当于问for(int i=0;i<balls.size;i++)是怎么实现的,
    这涉及到java编译器的实现问题,
    甚至是汇编或者机器码的问题,
    作为一个高级语言应用程序的开发者,这类问题不应该是关注的重点,
    我们更应该关注,怎样使用现有的语法和api,来实现需要的应用程序功能。
      

  5.   

    Graphics2D.fill方法可用来填充任何的图形,这段循环就是把那些球填充好
      

  6.   

    回5楼,。的确是一次吧。每次调用component.repaint();时,
    public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;
    for (Ball b : balls) {
    g2.fill(b.getShape());
    }
    里面的代码会显示一次。
    我这个是小球滚动的小程序,在相隔一定的时间,会重画一次,达到滚动的效果
      

  7.   

    间隔重绘面板,面板绘制主要动作是填充每一个Ball对象,每个Ball都有一个单独的线程控制
      

  8.   

    那这个程序点击启动按钮后,只有一个线程,还是多个线程?如果是多个线程,又是为什么 
    private ArrayList<Ball> balls = new ArrayList<Ball>();这句到底定义了什么 
      

  9.   

    点击一次启动按钮,受按钮点击事件触发新增了一个线程,每点击一次,新增一个actionPerformed => addBall 
                          |
                          V Runnable r = new BallRunnable(b, panel);
    Thread t = new Thread(r);
    t.start();
    private ArrayList<Ball> balls = new ArrayList<Ball>();
    这句可以说是只装载球对象的集合,当然是可以动态装卸的