自定义模态对话框

时间:2012-11-01 16:02:28

标签: java multithreading swing swingutilities invokelater

我正在创建自己的对话框,它基本上是一个JPanel设置为JFrame上的glasspane。我希望在对话框可见时不执行setVisible()之后的所有代码的意义上创建对话框模态,一旦对话框关闭,setVisible()之后的其余代码必须继续。

为了达到这个目的,我使用一个线程来显示我的对话框。我知道必须使用SwingUtilities.invokeLater()方法来更新gui,因为它是在另一个线程中执行的。但是我的对话框没有显示在屏幕上。

这是我的代码示例:

final JFrame frame = new JFrame();
frame.setBounds(0, 0, 1024, 768);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);

JButton button = new JButton("Text");
button.setBounds(200, 300, 110, 50);
button.addActionListener(new ActionListener() {

    boolean dispose;

    public void actionPerformed(ActionEvent e) {
        try {
            Thread thread = new Thread(new Runnable() {
                public void run() {
                    final JPanel panelGlass = new JPanel(null);
                    panelGlass.setBounds(frame.getBounds());
                    panelGlass.setBackground(Color.red);
                    frame.setGlassPane(panelGlass);

                    JButton btnClose = new JButton("close");
                    btnClose.setBounds(100, 100, 110, 50);
                    btnClose.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
                            dispose = true;
                        }
                    });
                    panelGlass.add(btnClose);

                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            dispose = false;
                            panelGlass.setVisible(true);
                        }
                    });

                    while (!dispose) {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException ex) {
                            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                    panelGlass.setVisible(false);
                }
            });
            thread.start();
            thread.join();
        } catch (Exception ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
});
frame.getContentPane().add(button);

frame.setVisible(true);

为什么我的对话框没有显示?

3 个答案:

答案 0 :(得分:1)

问题在于:

thread.start();
thread.join();

你启动线程,但你马上等待它完成。这会阻止UI线程,并且不允许它处理您的SwingUtilities.invokeLater更新。

我认为没有任何充分的理由要求join呼叫存在。

答案 1 :(得分:1)

你不能那样做,因为

  • 您正在从事件调度线程以外的线程访问Swing组件
  • 调用Thread.join()完全阻止事件调度线程,其中所有UI绘制都发生了。

你应该能够用Java 7 SecondaryLoop做你想做的事情,但我从来没有用过它。

答案 2 :(得分:1)

  • frame.getRootPane.setGlassPane

  • 你的想法很好,但是必须使用来自键盘的consume()事件,只使用e.consume()添加KeyListener,因为GlassPane只使用鼠标事件

  • 使用GlassPane创建整个Gui,

  • 内部执行操作以显示准备好的GlassPane,然后启动Runnable.Thread

  • 我在这里有一个关于乘法玻璃板的问题

  • 使用JLayer Java7,基于JXLayer Java6

  • 您的问题是为什么原因是用Java实现SwingWorker的预订示例

手机回复