我正在尝试将paintcall全局变量初始化为已经存在的ballGUI对象。我必须这样做才能在我的运行函数中为多线程调用重新绘制方法,这样就不会为每个单独的球创建一个新的GUI。为空间保留的导入。
import java.awt.Color;
public class BallT extends Thread implements Runnable {
private static int xcord, ycord, ychange, xchange;
private static boolean xUp;
private static boolean yUp;
private Color color;
private BallGUI paintcall=//? existing object BallGUI ;
public BallT(int x, int y) {
yUp = false;
xUp = false;
xcord = x;
ycord = y;
color = new Color((int) Math.random(), (int) Math.random(),
(int) Math.random());
}
public Color getColor() {
return color;
}
public int getX() {
return xcord;
}
public int getY() {
return ycord;
}
public void run() {
while (true) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
if (xUp == true) {
xcord = xcord + xchange;
} else {
xcord = xcord - xchange;
}
if (yUp == true) {
ycord = ycord + ychange;
} else {
ycord = ycord - ychange;
}
if (xcord <= 0) {
xUp = true;
xchange = (int) Math.random() * 5;
} else if (xcord > 340) {
xUp = false;
xchange = (int) Math.random() * 5;
}
if (ycord <= 0) {
yUp = true;
ychange = (int) Math.random() * 5;
} else if (ycord > 340) {
yUp = false;
ychange = (int) Math.random() * 5;
}
paintcall.repaint();
}
}
}
@SuppressWarnings("serial")
public class BallGUI extends JFrame {
public JPanel ballappear;
private final int maxBalls = 20;
private BallT[] balls;
private int count;
private ExecutorService threadPool = Executors.newCachedThreadPool();
public BallGUI() {
super("Bouncing");
ballappear = new JPanel();
count = 0;
balls = new BallT[20];
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
makeBall(e);
}
});
add(ballappear);
}
private void makeBall(MouseEvent e) {
if (count < maxBalls - 1) {
int x = e.getX();
int y = e.getY();
balls[count] = new BallT(x, y);
threadPool.execute(balls[count]);
count++;
}
}
@Override
public void paint(Graphics g) {
super.paint(g);
for (int i = 0; i < count; i++) {
g.setColor(Color.BLACK);
g.fillOval(balls[i].getX(), 340, 10, 10);
g.setColor(balls[i].getColor());
g.fillOval(balls[i].getX(), balls[i].getY(), 10, 10);
}
}
}
首先是简单的解决方案-更改BallT构造函数以获取BallGUI实例:
public BallT(int x, int y, BallGUI ballGUI) {
this.paintcall = ballGUI;
yUp = false;
//...
接下来,在GUI对象中的构造过程中传入实例:
private void makeBall(MouseEvent e) {
if (count < maxBalls - 1) {
// ...
balls[count] = new BallT(x, y, this);
}
}
然而,根据良好的模型-视图-控制器(MVC)设计实践,这是背靠背的。通常,视图(BallGUI)应该知道模型(BallT),但模型应该不知道视图。BallGUI已经维护了一个BallT的列表,它可能会在paint()方法中查询该列表。我会考虑有一个控制器,它负责依次在每个BallT上调用updatePosition()方法,然后在GUI上调用repaint()。这还有一个优点,即您不需要为每个球创建一个新的线程,而只需要一个控制器线程。