web-dev-qa-db-ja.com

JavaでSwingWorkerを使用するにはどうすればよいですか?

以前の質問に関連して: Javaの別のクラスから再描画を呼び出しますか?

私はJavaが初めてで、SwingWorkerのチュートリアルを見たことがあります。しかし、前の質問で与えたサンプルコードでそれを実装する方法がわかりません。

誰でも私のコードスニペットに関してSwingWorkerの使用方法を説明したり、適切なチュートリアルを教えてくれたりできますか?見たことがありますが、まだ理解しているかはわかりません。

42
Relequestual

通常、SwingWorkerは、Swingで長時間実行されるタスクを実行するために使用されます。

Event Dispatch Thread(EDT)で長時間実行されるタスクを実行すると、GUIがロックアップする可能性があるため、行われたことの1つは SwingUtilities.invokeLater および invokeAndWait これは、目的のタスク(Runnableの形式)を実行する前に他のAWTイベントを優先させるGUIの応答性を維持します。

ただし、SwingUtilitiesの問題は、実行されたRunnableから元のメソッドにデータを返すことができないことです。これが SwingWorker が対処するために設計されたものです。

Javaチュートリアルには SwingWorker に関するセクションがあります。

SwingWorkerを使用して別のスレッドで時間のかかるタスクを実行し、1秒後にメッセージボックスに答えを表示する例を次に示します。

最初に、SwingWorkerを拡張するクラスが作成されます。

class AnswerWorker extends SwingWorker<Integer, Integer>
{
    protected Integer doInBackground() throws Exception
    {
        // Do a time-consuming task.
        Thread.sleep(1000);
        return 42;
    }

    protected void done()
    {
        try
        {
            JOptionPane.showMessageDialog(f, get());
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

doInBackgroundおよびgetメソッドの戻り値の型はSwingWorkerの最初の型として指定され、2番目の型はpublishおよびprocessメソッド。この例では使用されません。

次に、SwingWorkerを呼び出すために、executeメソッドが呼び出されます。この例では、ActionListenerJButtonにフックして、AnswerWorkerを実行します。

JButton b = new JButton("Answer!");
b.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e)
    {
        new AnswerWorker().execute();
    }
});

上記のボタンをJFrameに追加し、クリックしてすぐにメッセージボックスを表示できます。以下を使用して、SwingアプリケーションのGUIを初期化できます。

private void makeGUI()
{
    final JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.getContentPane().setLayout(new FlowLayout());

    // include: "class AnswerWorker" code here.
    // include: "JButton" b code here.

    f.getContentPane().add(b);
    f.getContentPane().add(new JButton("Nothing"));
    f.pack();
    f.setVisible(true);
}

アプリケーションが実行されると、2つのボタンが表示されます。 「Answer!」というラベルの付いたものそしてもう一つの「何もない」。 「Answer!」をクリックするとボタン、最初は何も起こりませんが、「なし」ボタンをクリックすると動作し、GUIが応答することを示します。

そして、1秒後、AnswerWorkerの結果がメッセージボックスに表示されます。

105
coobird

同意する:

Event Dispatch Thread(EDT)で長時間実行されるタスクを実行すると、GUIがロックする可能性があります。

同意しない:

そのため、行われたことの1つは、SwingUtilities.invokeLaterとinvokeAndWaitを使用してGUIの応答性を維持することです。

invokeLaterは引き続きEDTでコードを実行し、UIをフリーズできます!!これを試して:

SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(100000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

少なくとも、上記のコードでactionPerformedをトリガーするボタンをクリックすると、マウスを移動できません。何か不足していますか?

7