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

所以,我立刻想到了两件事。

  1. 使用java.util.Timer

Swing 不是线程安全的,因为 java.util.Timer 在它自己的线程中运行,更新 UI (或者在这种情况下,UI 依赖的东西)可能会导致你随机问题。

我会考虑使用 javax.swing.Timer,因为它是在事件调度队列内部触发的(并且通常更易于使用)

  1. 不打电话 super.paint

你没有考虑到 paint 的作用,也没有接管它的责任,在这种情况下,"prepare" Graphics 的上下文绘画。

Graphics是一个共享资源,它被传递给所有在paint pass中被更新的组件。这意味着它将包含以前绘制的内容。

两条建议:

  1. 作为一般建议,更喜欢覆盖 paintComponent 而不是 paintpaint 做了很多重要的工作,所以除非你愿意做它们,否则通常油漆链中的高位)
  2. 在进行任何自定义绘画之前先调用 super.paintComponent

我强烈推荐阅读: