【问题标题】:Is there a way to resize my JFrame without drawing excess shapes?有没有办法在不绘制多余形状的情况下调整 JFrame 的大小?
【发布时间】:2019-09-26 05:33:17
【问题描述】:

我正在编写一个程序,它会在窗口内每隔一段时间绘制随机形状。我希望将形状存储在一个数组中,因为稍后我需要从文本文件中检索每个形状的信息。只要我不尝试调整窗口大小,它就可以正常工作。每当我拉伸它时,都会出现很多新形状(比预期的要快),可能是因为每次调整大小时都会调用 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;
        }
    }

}

【问题讨论】:

    标签: java swing jframe awt drawing


    【解决方案1】:

    您不能从绘画方法调用addShape。正如您所发现的,您无法控制何时调用绘画方法。调整大小并不是唯一可以触发绘画的事情。移动或升高窗户都可以。即使将鼠标移到窗口上也可以。永远不要在绘画方法中更改您的数据。

    在其他地方更改您的数据,例如在调用 repaint() 之前。所有 Swing 操作都需要在 AWT 事件调度线程中进行,并且 Swing 操作使用的数据也需要在该线程中进行修改(除非您采取措施使代码线程安全,例如同步)。在该线程中定期执行代码的最简单方法是使用 javax.swing.Timer 类:

    public Timer drawThread() {
        return new Timer(1000, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                addShape();
                repaint();
            }
        });
    }
    

    请注意,与线程类似,Timer 需要调用其start()(或restart())方法。

    【讨论】:

    • (1+) 另外,不要覆盖框架上的paint()。自定义绘画是通过覆盖 JPanel 的 paintComponent() 来完成的,然后将面板添加到框架中。阅读 Custom Painting 上的 Swing 教程部分,了解更多信息和工作示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-27
    • 2019-10-01
    • 1970-01-01
    • 2011-06-04
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多