【问题标题】:Custom Modal Dialog自定义模式对话框
【发布时间】:2012-11-01 16:02:27
【问题描述】:

我正在创建自己的对话框,它基本上是一个 JPanel,设置为 JFrame 上的玻璃窗格。我想让我的对话框模态化,因为当对话框可见时 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);

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

【问题讨论】:

  • 有什么原因不能使用 JDialog 创建自定义对话框吗?
  • 是的,我正在绘制自己的对话框,它们是透明的,这使得 JPanel 比标准 JDialog 更容易

标签: java multithreading swing swingutilities invokelater


【解决方案1】:

问题出在这里:

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

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

我真的认为join 调用存在的任何充分理由。

【讨论】:

  • 正如我在问题中解释的那样,我需要执行代码以等待我的对话框关闭才能继续,类似于 JOptionPane.showMessageDialog(null, "This is a message");
  • @bouncer:这显然不能正常工作。但正如我从使用swing 中回忆的那样,您实际上并不需要一个新线程来在主线程之上显示另一个控件。您只需要找出一种方法,在关闭新控件之前不让主控件可访问。
【解决方案2】:

你不能那样做,因为

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

您应该能够使用 Java 7 的 SecondaryLoop 执行您想要的操作,但我从未使用过它。

【讨论】:

  • 不幸的是,我目前正在使用 Java 6。
【解决方案3】:
  • frame.getRootPane.setGlassPane

  • 您的想法不错,但必须使用来自键盘的 consume() 事件,仅使用 e.consume() 添加 KeyListener,因为 GlassPane 仅使用鼠标事件

  • 也可以使用 GlassPane 创建整个 Gui,

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

  • 我有一个关于多层玻璃板的问题

  • 使用JLayer Java7,基于JXLayer Java6

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

手机回复

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-05
    • 2021-05-31
    • 2016-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多