从许多不同的 类 中更新一个 JTextPane

Updating one JTextPane out of many different classes

我必须通过一个按钮来同步两个数据库。在按钮下,我在 JScrollPanel 中有一个 JTextPane。我的 TextPane class 看起来像:

public class InfoArea extends JTextPane {
  private final HTMLEditorKit   kit              = new HTMLEditorKit();
  private final HTMLDocument    doc              = new HTMLDocument();
  private static ia;

  public static InfoArea getInfoArea {
    if (ia == null) ia = new InfoArea();
    return ia;
  }

  private InfoArea() {
    setEditorKit(kit);
    setDocument(doc);

    showInfo("Please wait...");

    setEditable(false);
  }

  public void showInfo(String msg) {

    try {
      kit.insertHTML(doc, doc.getLength(), "<b><font color=\"#00AA00\">" + msg + "</font></b>", 0, 0, null);
    } catch (BadLocationException | IOException e) {
      e.printStackTrace();
    }
  }
}

"TextPane" 已添加到 GUI 中的 SOUTH。

现在我有一些 classes 可以:

private static final InfoArea ia = InfoArea.getInfoArea();

首先我初始化数据库连接。因为这完成得非常快,所以信息会立即显示。但后来我做了这样的事情:

private void doSmth() {
  for(int i = 0; i < smth; ++i) {
    if(sync()) ia.showInfo("OK");
    else ia.showInfo("Not OK");
  }
}

在其他 classes 中,结果集可能需要一段时间。问题是,直到每个方法都运行完后,文本窗格才会更新。我对这种行为很生气,我知道问题出在事件调度程序线程 (EDT) 上。我尝试更新 showInfo(String msg) 如下:

private void showInfo(String msg) {
  SwingUtilities.invokeLater(new Runnable() {

    public void run() {

      try {
          kit.insertHTML(doc, doc.getLength(), msg, 0, 0, null);
      } catch (BadLocationException | IOException e) {
          e.printStackTrace();
      }
    }
  });
}

但这并不能解决问题。我也尝试过覆盖 doInBackground()、publish() 和 process() 的 SwingWorker,但也没有成功。我还尝试了工作线程而不是 SwingUitilities。我最后试过:

private void doSmth() {
  for(int i = 0; i < smth; ++i) {
    SwingUtilities.invokeLater(new Runnable() {

      public void run() {
        if(sync()) ia.showInfo("OK");
        else ia.showInfo("Not OK");
      }
    });
  }
}

没有成功。我也认为这个尝试是最糟糕的,因为它阻止了 EDT。

正如您可能注意到的那样,我现在有点绝望,因为我不知道该往哪里看。很抱歉没有 post 对 SwingWorker 和 WorkerThreads 进行所有尝试,但他们会破坏这个 post。而且已经够大了。

有人可以告诉我,我必须做什么才能让它工作吗?对于希望在同步过程 运行 期间查看内容的客户,我需要它。如果有遗漏,我也愿意提供更多信息。

自己解决了。我误解了昨天我红的一些文章。解决方案是,将整个任务放在一个线程中,而不仅仅是输出的方法。

正如我所说,我单击一个按钮开始同步过程。该按钮仅调用一个方法:

public void syncDB() {

  ia.showInfo("Sync cat...");
  doCatSync();

  ia.showInfo("Sync item...");
  doItemSync();
  ...
}

现在我必须围绕这些任务进行讨论:

public void syncDB() {

  new Thread() {

    public void run() {

      ia.showInfo("Sync cat...");
      doCatSync();

      ia.showInfo("Sync item...");
      doItemSync();
      ...
    }
  }.start();
}

成功了。我总是乐于改进。