2

SwingUtilities.invokeLater()の使用法を紹介する例を書いていました。私が書いたこの単純な例(コードを含む)は、invokeLater()の使用を保証するものではないことに気づきました。invokeLater()を使用する必要がある場合がありましたが、いつどこで使用したかを忘れてしまいました。また、EDP以外のスレッドでは、invokeLater()を使用する必要があることも理解していますが、私の場合はそれは必要ないようで、正常に機能しました。このコードでinvokeLater()を使用する必要がない理由を誰かにアドバイスしてもらいたいと思っていました。ショーケースコードにバグがないことを願っています。

ところで、私はLinuxとWindowsでJDK 1.6/1.7を使用しています。

ありがとう。

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class HelloButton {
    public static void main(String[] args) {
        JFrame f = new JFrame();
        f.setLayout(new FlowLayout());
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        JSplitPane pane = new JSplitPane();
        f.add(pane);
        final JLabel clickMessage = new JLabel("No Message at " + System.currentTimeMillis());
        pane.setLeftComponent(clickMessage);
        JButton clickMe = new JButton("Click me");
        clickMe.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                threadedIntensiveProcess(clickMessage);
//                intensiveProcess(clickMessage);
            }
        });
        pane.setRightComponent(clickMe);

        f.pack();
        f.setVisible(true);
    }

    static private void threadedIntensiveProcess(final JLabel label)
    {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("UI Thread : " + SwingUtilities.isEventDispatchThread());
                intensiveProcess(label);
            }
        }).start();
    }

    static private void intensiveProcess(JLabel label)
    {
        label.setText("was clicked at " + System.currentTimeMillis());
        for (int i = 0; i < 3; i++)
        {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
            label.setText("was updated at " + System.currentTimeMillis());
        }
        System.out.println(label.getText());
    }
}
4

1 に答える 1

3

を使用する必要がある状況が 2 つありますinvokeLater

  1. UIの作成。
  2. の更新JLabel

UI の作成全体は EDT で行う必要があります。古代の Swing の時代には、メイン スレッドまで、またはその時点まではスレッド化の問題が発生しないため、任意の作成を行うことができると言われshowsetVisible(true)ました。これは疑わしいものであったため、現在は推奨されていません。あなたの場合のように、明らかに動作するかもしれませんが、保証はありません。

このコンテキストで in が適切に動作するsetTextことは幸運です。JLabelメソッドがスレッドセーフであることは API によって保証されていないため、他の Swing メソッドの呼び出しと同様に、EDT でこのメソッドを呼び出す必要があります。

つまり、結論として、うまくいくように見える簡単な例があります-それは簡単で、あなたは幸運だからです。そのような「テスト」に頼るのではなく、ドキュメントに頼ってください。ショーケースにコードの表示が含まれている場合は、間違っていないために呼び出しを EDT に移動する必要があります。

あなたのコードがinvokeLater.

于 2012-02-21T06:59:36.820 に答える