2
JDialog dialog = new JDialog(parent JFrame, "blabla");
dialog.setLayout(new BorderLayout());

JLabel label = new JLabel("more blabla");

dialog.getContentPane().add(label, BorderLayout.CENTER);

dialog.setSize(new Dimension(280, 80));
dialog.setLocationRelativeTo(parent JFrame);
dialog.setVisible(true);

//part of code that takes time to execute
//actually, I'm sending an email here, but it doesn't really matter what I do,
//as you will read below        

dialog.dispose();

我有上面的代码,它的用途是在执行某些代码时向用户显示一条消息(代码的执行大约需要 5-10 秒,我不希望用户认为程序冻结)。

问题是,添加到对话框中的 JLabel 根本没有出现。无论我添加到对话框中,确切地说,它都不会出现。

但是,如果我将 JDialog 设置为模态(将 true 作为上述构造函数的最后一个参数添加),它会出现,但是我想要执行的代码在对话框关闭之前不会运行,这违背了它的目的。

由于它在代码中的位置,将要执行的代码并不重要,我尝试将其保留在当前上方 - 根本没有执行代码 - 对话框会出现一瞬间,但我可以看到它是空的。

我知道我可以创建一个确认窗口并说“等待 10 秒,代码正在执行”,但我不想那样做。

我还尝试将 JDialog 换成 JFrame,文本仍然不会出现。

我错过了什么?

4

1 回答 1

7

如果长时间运行的任务在Event Dispatch Thread(EDT) 上执行,则对话框可能没有机会自行绘制/重绘,直到任务完成。有关 EDT 的更多详细信息,请查看Swing 中的并发教程。

这是一个使用您的代码的示例,它演示了行为不端的对话框

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class TestDialog {

    private static void createAndShowGUI() {
        final JFrame frame = new JFrame("Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JButton button = new JButton("Execute");
        button.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                final JDialog dialog = new JDialog((JFrame)frame, "blabla");
                dialog.setLayout(new BorderLayout());
                JLabel label = new JLabel("more blabla");
                dialog.getContentPane().add(label, BorderLayout.CENTER);

                dialog.setSize(new Dimension(280, 80));
                dialog.setLocationRelativeTo(frame);
                dialog.setVisible(true);

                try {
                    Thread.sleep(3000);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }

                dialog.setVisible(false);
                dialog.dispose();
            }

        });

        frame.add(button);          
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

考虑通过在工作线程上执行长时间运行的任务来重构您的实现。例如,您可以使用SwingWorker来实现。

这是一个演示,用一个简单的工作人员说明了相同的对话框:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingWorker;

public class TestDialogWithWorker {

    private static void createAndShowGUI() {
        final JFrame frame = new JFrame("Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JButton button = new JButton("Execute");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                new Worker(frame).execute();
            }

        });

        frame.add(button);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    static class Worker extends SwingWorker<Void, Void> {
        JDialog dialog;

        public Worker(JFrame parent) {
            dialog = new JDialog((JFrame) parent, "blabla");
            dialog.setLayout(new BorderLayout());
            JLabel label = new JLabel("more blabla");
            dialog.getContentPane().add(label, BorderLayout.CENTER);

            dialog.setSize(new Dimension(280, 80));
            dialog.setLocationRelativeTo(parent);
            dialog.setVisible(true);
        }

        @Override
        protected Void doInBackground() throws Exception {
            Thread.sleep(3000);
            return null;
        }

        @Override
        protected void done() {
            dialog.setVisible(false);
            dialog.dispose();

            try {
                get();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }       
}
于 2012-09-13T01:30:13.453 回答