Java 当我尝试从面板中删除形状时,repaint() 方法不起作用
Java repaint() method doesn't work when I try to delete shapes from panel
我想每秒画一些圆圈,然后将它们全部(或至少一个)从面板中删除。
这是现有的代码:
public class DrawShape {
ShapePanel panel;
public DrawShape(ShapePanel panel) {
this.panel = panel;
Timer t = new Timer();
t.schedule(new TimerTask() {
long startTime = System.currentTimeMillis();
int secondsToRun = 3;
@Override
public void run() {
if (System.currentTimeMillis() - startTime > secondsToRun * 1000) {
panel.deleteCircle();
System.out.println("\t" + panel.circles.size());
cancel();
} else {
panel.addCircle(new Circle((int) (Math.random() * 200), (int) (Math.random() * 200)));
System.out.println(panel.circles.size());
}
}
}, 0, 1000);
}
}
如果时间大于3秒,则删除所有圆圈,否则继续在屏幕上画圆圈。
这里是 ShapePanel class:
public class ShapePanel extends JPanel {
public List<Circle> circles = new LinkedList<Circle>();
public ShapePanel() {
// Setting up the frame
JFrame frame = new JFrame();
frame.setSize(500, 500);
frame.setVisible(true);
frame.setBackground(Color.black);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(this); // adding the panel to the frame
}
public void addCircle(Circle circle) {
circles.add(circle);
this.repaint();
}
public void deleteCircle() {
// circles.remove(circles.get(0));
circles.clear(); //remove them all
this.repaint();
}
@Override
public void paint(Graphics g) {
for (Circle c : circles) {
g.setColor(Color.GREEN);
g.drawOval(c.x, c.y, Circle.radius * 2, Circle.radius * 2);
}
}
}
当我调用 deleteCircle() 时,圆应该从列表中删除并重新绘制。我最终应该得到一个没有圆圈的空白屏幕。我认为重绘在这种情况下不起作用。
P.S.: 第一次提问,很长很抱歉:D
所以,我立刻想到了两件事。
- 使用
java.util.Timer
Swing 不是线程安全的,因为 java.util.Timer
在它自己的线程中运行,更新 UI (或者在这种情况下,UI 依赖的东西)可能会导致你随机问题。
我会考虑使用 javax.swing.Timer
,因为它是在事件调度队列内部触发的(并且通常更易于使用)
- 不打电话
super.paint
你没有考虑到 paint
的作用,也没有接管它的责任,在这种情况下,"prepare" Graphics
的上下文绘画。
Graphics
是一个共享资源,它被传递给所有在paint pass中被更新的组件。这意味着它将包含以前绘制的内容。
两条建议:
- 作为一般建议,更喜欢覆盖
paintComponent
而不是 paint
(paint
做了很多重要的工作,所以除非你愿意做它们,否则通常油漆链中的高位)
- 在进行任何自定义绘画之前先调用
super.paintComponent
。
我强烈推荐阅读:
和
我想每秒画一些圆圈,然后将它们全部(或至少一个)从面板中删除。
这是现有的代码:
public class DrawShape {
ShapePanel panel;
public DrawShape(ShapePanel panel) {
this.panel = panel;
Timer t = new Timer();
t.schedule(new TimerTask() {
long startTime = System.currentTimeMillis();
int secondsToRun = 3;
@Override
public void run() {
if (System.currentTimeMillis() - startTime > secondsToRun * 1000) {
panel.deleteCircle();
System.out.println("\t" + panel.circles.size());
cancel();
} else {
panel.addCircle(new Circle((int) (Math.random() * 200), (int) (Math.random() * 200)));
System.out.println(panel.circles.size());
}
}
}, 0, 1000);
}
}
如果时间大于3秒,则删除所有圆圈,否则继续在屏幕上画圆圈。
这里是 ShapePanel class:
public class ShapePanel extends JPanel {
public List<Circle> circles = new LinkedList<Circle>();
public ShapePanel() {
// Setting up the frame
JFrame frame = new JFrame();
frame.setSize(500, 500);
frame.setVisible(true);
frame.setBackground(Color.black);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(this); // adding the panel to the frame
}
public void addCircle(Circle circle) {
circles.add(circle);
this.repaint();
}
public void deleteCircle() {
// circles.remove(circles.get(0));
circles.clear(); //remove them all
this.repaint();
}
@Override
public void paint(Graphics g) {
for (Circle c : circles) {
g.setColor(Color.GREEN);
g.drawOval(c.x, c.y, Circle.radius * 2, Circle.radius * 2);
}
}
}
当我调用 deleteCircle() 时,圆应该从列表中删除并重新绘制。我最终应该得到一个没有圆圈的空白屏幕。我认为重绘在这种情况下不起作用。
P.S.: 第一次提问,很长很抱歉:D
所以,我立刻想到了两件事。
- 使用
java.util.Timer
Swing 不是线程安全的,因为 java.util.Timer
在它自己的线程中运行,更新 UI (或者在这种情况下,UI 依赖的东西)可能会导致你随机问题。
我会考虑使用 javax.swing.Timer
,因为它是在事件调度队列内部触发的(并且通常更易于使用)
- 不打电话
super.paint
你没有考虑到 paint
的作用,也没有接管它的责任,在这种情况下,"prepare" Graphics
的上下文绘画。
Graphics
是一个共享资源,它被传递给所有在paint pass中被更新的组件。这意味着它将包含以前绘制的内容。
两条建议:
- 作为一般建议,更喜欢覆盖
paintComponent
而不是paint
(paint
做了很多重要的工作,所以除非你愿意做它们,否则通常油漆链中的高位) - 在进行任何自定义绘画之前先调用
super.paintComponent
。
我强烈推荐阅读:
和