1

我不明白如何将程序的核心与程序的 GUI 部分分开。实际上,网络上的所有示例都表明任何 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 部分和核心部分分开?而且,如果答案是肯定的,我该怎么做?

如果可能的话,我需要 EDT 调用对使用 GUI 类的用户是透明的。

编辑:

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

问题是你不能在同一个线程中运行你的计算和你的 GUI。如果您这样做,您的 GUI 将在您的代码进行数字运算时冻结。一种方法是在单独的线程中运行您的计算,然后使用 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 回答
1

您可以在GUI课堂上隐藏事件调度线程 (EDT) 的使用。只有与 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 回答