Java CardLayout .show()没有显示

时间:2015-10-05 14:49:05

标签: java swing cardlayout

我在像“while”循环这样的“阻塞”代码之前使用.show()。但即使调用.show,UI也不会实际显示被调用的面板。

以下是显示问题的代码: (警告:此代码包含while循环。)

import javax.swing.JFrame;
import java.awt.CardLayout;
import java.awt.event.ActionEvent;

import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JButton;

public class CardTest extends JFrame{
public CardTest() {
    CardLayout cl = new CardLayout(0,0);
    getContentPane().setLayout(cl);

    JPanel panelA = new JPanel();
    getContentPane().add(panelA, "PanelA");

    JLabel lblPanelA = new JLabel("Panel A");
    panelA.add(lblPanelA);

    JButton btnSwitchToPanel = new JButton("Switch to Panel B");
    panelA.add(btnSwitchToPanel);

    JPanel panelB = new JPanel();
    getContentPane().add(panelB, "PanelB");

    JLabel lblPanelB = new JLabel("Panel B");
    panelB.add(lblPanelB);

    btnSwitchToPanel.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(ActionEvent event) {
            cl.show(getContentPane(), "PanelB");
            getContentPane().revalidate();

            // Here is the problem. Even though cl.show is called first, 
            // it still doesn't show, before the while loop has terminated.
            int i = 0;
            while(i < 1000000){
                i++;
                System.out.println(i);
            }
        }
    });

    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    pack();
    setVisible(true);
}

public static void main(String[] args){
    new CardTest();
}
}

如果您想知道,我需要这个下载器,在第一个面板中按下按钮后调用while true循环(下载文件)。第二个面板包含进度条。但即使在下载代码之前调用.show函数,也不会显示进度面板。

更新

我知道将循环放入一个新线程,解决了绘制问题,但它也引入了其他问题,因为我依赖循环后的顺序执行函数(下载文件(循环),Unzipp文件,移动那些文件...)。

最好的解决方案是找到一种方法,允许.show()调用在继续循环之前实际花时间切换窗格。

3 个答案:

答案 0 :(得分:3)

  

我在&#34;阻止&#34;之前使用.show()代码就像一个while循环。但即使.show被调用,UI也没有实际显示被调用的面板。

是的,因为你是&#34;阻止&#34;事件调度线程(EDT)负责重新绘制GUI。因此GUI不能重新绘制自己,直到代码完成执行。

您需要创建一个单独的线程来执行长时间运行的任务,这样您就不会阻止EDT。一种方法是使用SwingWorker。 SwingWorker将为您创建线程,并在任务完成时通知您,以便您可以更新GUI。

阅读Concurrency上Swing教程中的部分,了解更多信息和工作示例。

答案 1 :(得分:2)

这是因为您正在对EventDispatchingThread进行操作。此线程还负责实际绘制GUI。

除了在另一个主题中开展工作之外别无选择。

例如:(快速+肮脏)

new Thread(){
    @Override
    public void run() {
        while (...) {...}
    }
}.start();

答案 2 :(得分:2)

这是因为重绘UI是在与事件处理相同的线程中完成的,并且直到事件处理完成之后才发生(即,所有事件处理方法都已返回)。

最好的办法是移动&#34;阻止&#34;将代码编译成runnable并在工作线程中执行它。