1

プログラムのコア部分とプログラムの GUI 部分を分離する方法がわかりません。実際、Web 上のすべての例では、GUI アクションは SwingUtilities.invokeLater() メソッドで実行する必要があると書かれています。

問題は、このメソッドを使用して GUI 部分のみを処理する方法と、コアと GUI が通信する方法を理解できないことです。

たとえば、いくつかの計算の GUI 表示を担当するクラスがあります。

public class GUI {
  private JFrame window;

  public GUI() {
    window = null;
  }

  public void createWindow(int width, int height) {
    window = new JFrame();
    ...
    window.setVisible(true);
  }

  public void displayResults(Calcul results) {
    /* Some Swing actions. */
  }
}

そして私は私のプログラムのコアを持っています:

public class Core {
  public static void main(String[] args) {
    GUI gui = new GUI();
    Calcul calculs = new Calcul();

    while (true) {
      /* Make some calculations. */
      /* Put results into calcul. */
      displayResults(calculs);
    }
  }
}

このアーキテクチャが理想的ではないことはわかっていますが、使用する必要があります。私の質問は、EDT を使用して GUI 部分とコア部分を分離する必要があるかどうかです。そして、答えが「はい」の場合、どうすればよいですか?

可能であれば、GUI クラスを使用するユーザーに対して EDT 呼び出しが透過的である必要があります。

編集:

次の GUI クラスの変換は期待どおりの動作をしますか?

public class GUI {
  private JFrame window;

  public GUI() {
    window = null;
  }

  public void createWindowEDT(final int width, final int height) {
    javax.swing.SwingUtilities.invokeLater(
      new Runnable() {
        public void run() {
          createWindow(width, height);
        }
      }
    );
  }

  private void createWindow(final int width, final int height) {
    window = new JFrame();
    ...
    window.setVisible(true);
  }

  public void displayResultsEDT(final Calcul results) {
    javax.swing.SwingUtilities.invokeLater(
      new Runnable() {
        public void run() {
          displayResultsEDT(results);
        }
      }
    );
  }

  private void displayResults(final Calcul results) {
    /* Some Swing actions. */
  }
}
4

3 に答える 3

1

GUI コードを EDT に配置するには、SwingUtilitiesクラスを使用します。Runnable インスタンスをinvokeLater()メソッドに渡す必要があります。

EDT でも GUI を作成する (GUI コンストラクターを呼び出す) 必要があります。

public static void main(String[] args) {

    GUI gui = null;
    Calcul calculs = new Calcul();

    SwingUtilities.invokeLater(
        new Runnable() {
             public void run() {
               gui = new GUI();
             }});


    while (true) {
    /* Make some calculations. */
    /* Put results into calcul. */
    javax.swing.SwingUtilities.invokeLater(
        new Runnable() {
             public void run() {
                 gui.displayResults(calculs);
             }});
    }
  }
于 2013-03-11T17:22:28.153 に答える
1

クラスでのイベント ディスパッチ スレッド (EDT) の使用を非表示にすることができますGUI。通常はスレッドセーフではない Swing コンポーネントであるため、EDT で実行する必要があるのは Swing コンポーネントとの対話だけです。

を呼び出すのはメイン アプリケーション スレッドだけであるため、GUI クラスで同期する必要はありませんがGUI.displayResults(Calcul)、これが変更された場合は、このメソッドを同期するか、スレッド エラーを回避するために他の手順を実行する必要があります。

public class GUI
{
  ...

  public void displayResults(Calcul results) 
  {
    SwingUtils.invokeLater(
      new Runnable()
      {
        public void run()
        {
          /* Some Swing actions. */
        }
      }
    );
  }
}
于 2013-03-11T18:03:26.770 に答える
1

問題は、同じスレッドで計算と GUI を実行できないことです。これを行うと、コードが数値計算を行っている間に GUI がフリーズします。1 つの方法は、別のスレッドで計算を実行し、そのスレッドから SwingUtilities.invokeLater() を使用して GUI に自身を更新するよう通知することです。例えば:

public static void main(String[] args) {
    final GUI myGUI = new GUI();

    Thread workThread = new Thread(new Runnable() {
        public void run() {
            // do calculations

            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    // update GUI
                    myGUI.updateMyResults();
                }
            });
        }
    });

    workThread.start();
}
于 2013-03-11T17:26:54.400 に答える