在循环中可视化JPanel更改

时间:2016-08-28 16:40:04

标签: java swing graphics

我是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);
        }
    });
}}

3 个答案:

答案 0 :(得分:2)

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

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

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

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

答案 1 :(得分:2)

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

如前所述@camickr对他的回答,你可以试试Swing Timer;这里的example完全符合您的要求。

根据您对其他答案的评论:

  

你能解释一下为什么&#34;重拍&#34;在循环中不起作用?为什么Timer没有&#34;重绘&#34;?

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

  

&#34; Swing非常聪明,可以在一次绘画操作中获取该信息并重新绘制屏幕的这些部分。换句话说,Swing不会连续两次重新绘制该组件,即使这是代码似乎正在执行的操作。&#34;

计时器将重新绘制它,因为它没有在EDT上运行但是在它自己的线程中

答案 2 :(得分:0)

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

public final void Test2() {

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

public  Test2() {

让程序做点什么。然后你可以进入下一步。

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