【问题标题】:visualizing JPanel change within a loop可视化循环内的 JPanel 更改
【发布时间】:2019-08-20 06:33:51
【问题描述】:

我是 Java swing 编程的新手。我想制作一个依次呈现红色和蓝色的框架。所以,我拿了 2 个子 JPanel,1 个用于红色,另一个用于蓝色,还有一个 for 循环。在每次迭代中,我从父面板中删除一个面板并添加另一个。但是,当我运行程序时,它只显示帧的最后状态。

谁能解释为什么?使程序像这样工作的预期方法是什么? 我的代码:

public class Test2 extends JFrame {

public Test2() {

    JPanel Red = new JPanel(new BorderLayout());
    JPanel Blue = new JPanel(new BorderLayout());

    //...initialize Red and Blue
    Red.setBackground(Color.red);
    Blue.setBackground(Color.blue);
    Red.setPreferredSize(new Dimension(200,200));
    Blue.setPreferredSize(new Dimension(200,200));


    JPanel panel = new JPanel(new BorderLayout());
    panel.setPreferredSize(new Dimension(200,200));

    add(panel);

    pack();

    setTitle("Border Example");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLocationRelativeTo(null);

    int M = 1000000; //note that, I made a long iteration to not finish the program fast and visualize the effect
    for(int i=0;i<M;i++)
    {
        if(i%(M/10)==0) System.out.println(i); //to detect whether the program is running

        if(i%2==0)
        {
            panel.removeAll();
            panel.repaint();
            panel.revalidate();
            panel.add(Red,BorderLayout.CENTER);
        }
        else
        {
            panel.removeAll();
            panel.repaint();
            panel.revalidate();
            panel.add(Blue,BorderLayout.CENTER);
        }
    }
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            Test2 ex = new Test2();
            ex.setVisible(true);
        }
    });
}}

【问题讨论】:

    标签: java swing graphics


    【解决方案1】:

    不要使用循环。 Swing 只会在整个循环完成执行后重新绘制帧。

    相反,您需要使用 Swing Timer。当 Timer 触发时,您会调用您的逻辑。阅读 How to Use Swing Timers 上的 Swing 教程部分。

    这是一个简单的计时器示例,它只是显示每秒的时间:Update a Label with a Swing Timer

    另外,请勿移除/添加面板。相反,您可以使用Card Layout 并摇摆可见面板。再次阅读How to Use CardLayout上的教程。

    【讨论】:

    • 你能解释一下为什么“重绘”不能循环工作吗?为什么计时器在没有“重绘”的情况下工作?
    • @agassaa,Swing 是单线程的。因此,在循环代码完成之前,无法重新绘制组件。阅读Concurrency 上的 Swing 教程以获取更多信息。
    【解决方案2】:

    基本上您不需要使用while(或任何其他)循环,Swing 仅在完成该循环后才进行绘制,然后重新绘制 GUI。

    正如@camickr 之前在他的回答中所说,您可以尝试Swing Timer;这是一个example,它完全符合您的要求。

    根据您对另一个答案的评论:

    你能解释一下为什么“重绘”不能循环工作吗?为什么定时器在没有“重绘”的情况下工作?

    Swing 足够聪明,知道它不需要在循环中重新绘制,而是在循环结束后重新绘制,如果您阅读第 3 步中Swing Custom Paint 上的教程,它会说:

    “Swing 足够聪明,可以在一次绘制操作中获取这些信息并重新绘制屏幕的这些部分。换句话说,Swing 不会连续两次重新绘制组件,即使那是代码似乎在做。”

    Timer 会重新绘制它,因为它不是在 EDT 上运行,而是在它自己的线程中运行

    【讨论】:

      【解决方案3】:

      我建议一次迈出一步。
      首先让它在不改变面板/颜色的情况下运行。
      现在不是因为这个

      public final void Test2() {
      

      是一种方法(从未使用过)而不是构造函数。 更改为构造函数声明,如:

      public  Test2() {
      

      让程序做一些事情。然后就可以进行下一步了。

      还使用 Java 命名约定(例如蓝色而不是蓝色)。

      【讨论】:

      • 对不起,我上传代码时出错了,请回我的帖子,我确实使用了构造函数。
      猜你喜欢
      • 2019-03-15
      • 1970-01-01
      • 2011-02-19
      • 1970-01-01
      • 2020-05-18
      • 1970-01-01
      • 2018-11-04
      • 2013-03-15
      • 1970-01-01
      相关资源
      最近更新 更多