有没有办法在不绘制多余形状的情况下调整 JFrame 的大小?
Is there a way to resize my JFrame without drawing excess shapes?
我正在编写一个程序,以一定间隔在 window 内绘制随机形状。我希望将形状存储在一个数组中,因为稍后我需要从文本文件中检索有关每个形状的信息。只要我不尝试调整 window 的大小,它就可以正常工作。每当我拉伸它时,都会出现很多新形状(比预期的要快),可能是因为每次调整大小时都会调用 repaint(),但我不知道如何防止它这样做。换句话说,如何防止在调整大小时出现多余的对象?
我将不胜感激任何提示,不仅是那些与我的问题直接相关的提示,还有我所做的任何编程选择。我是初学者。
希望我说清楚了。如果您需要,我很乐意提供更多详细信息。
public Window() {
setTitle("shapes");
setSize(800, 600);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setBackground(Color.DARK_GRAY);
setVisible(true);
}
public void paint(Graphics g) {
addShape();
g.clearRect(1,1, getWidth(), getHeight());
for (Figure figure : myFigures) {
figure.draw(g);
System.out.println(figure.toString());
}
}
public Thread drawThread() {
return new Thread(() -> {
while (true) {
repaint();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
private void addShape() {
int whichFigure = (int) (Math.random() * 3);
switch (whichFigure) {
case 1:
myFigures.add(new Oval((int) (Math.random() * getWidth()), (int) (Math.random() * getHeight()), (int) (Math.random() * 100), (int) (Math.random() * 100)));
System.out.println("oval added");
break;
case 2:
myFigures.add(new Rectangle((int) (Math.random() * getWidth()), (int) (Math.random() * getHeight()), (int) (Math.random() * 100), (int) (Math.random() * 100)));
System.out.println("rect added");
break;
}
}
}
您不得从绘画方法中调用 addShape
。正如您所发现的,您无法控制何时调用绘画方法。调整大小并不是唯一可以触发绘画的东西。移动或举起 window 罐头。即使将鼠标移到window 上也可以。永远不要在绘画方法中更改您的数据。
在另一个地方更改您的数据,例如在调用 repaint() 之前。所有 Swing 操作都需要在 AWT 事件派发线程中进行,Swing 操作使用的数据也需要在该线程中进行修改(除非您采取措施使代码 thread-safe,例如同步)。在该线程中定期执行代码的最简单方法是使用 javax.swing.Timer class:
public Timer drawThread() {
return new Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
addShape();
repaint();
}
});
}
我正在编写一个程序,以一定间隔在 window 内绘制随机形状。我希望将形状存储在一个数组中,因为稍后我需要从文本文件中检索有关每个形状的信息。只要我不尝试调整 window 的大小,它就可以正常工作。每当我拉伸它时,都会出现很多新形状(比预期的要快),可能是因为每次调整大小时都会调用 repaint(),但我不知道如何防止它这样做。换句话说,如何防止在调整大小时出现多余的对象?
我将不胜感激任何提示,不仅是那些与我的问题直接相关的提示,还有我所做的任何编程选择。我是初学者。
希望我说清楚了。如果您需要,我很乐意提供更多详细信息。
public Window() {
setTitle("shapes");
setSize(800, 600);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setBackground(Color.DARK_GRAY);
setVisible(true);
}
public void paint(Graphics g) {
addShape();
g.clearRect(1,1, getWidth(), getHeight());
for (Figure figure : myFigures) {
figure.draw(g);
System.out.println(figure.toString());
}
}
public Thread drawThread() {
return new Thread(() -> {
while (true) {
repaint();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
private void addShape() {
int whichFigure = (int) (Math.random() * 3);
switch (whichFigure) {
case 1:
myFigures.add(new Oval((int) (Math.random() * getWidth()), (int) (Math.random() * getHeight()), (int) (Math.random() * 100), (int) (Math.random() * 100)));
System.out.println("oval added");
break;
case 2:
myFigures.add(new Rectangle((int) (Math.random() * getWidth()), (int) (Math.random() * getHeight()), (int) (Math.random() * 100), (int) (Math.random() * 100)));
System.out.println("rect added");
break;
}
}
}
您不得从绘画方法中调用 addShape
。正如您所发现的,您无法控制何时调用绘画方法。调整大小并不是唯一可以触发绘画的东西。移动或举起 window 罐头。即使将鼠标移到window 上也可以。永远不要在绘画方法中更改您的数据。
在另一个地方更改您的数据,例如在调用 repaint() 之前。所有 Swing 操作都需要在 AWT 事件派发线程中进行,Swing 操作使用的数据也需要在该线程中进行修改(除非您采取措施使代码 thread-safe,例如同步)。在该线程中定期执行代码的最简单方法是使用 javax.swing.Timer class:
public Timer drawThread() {
return new Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
addShape();
repaint();
}
});
}