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 に答える