从许多不同的 类 中更新一个 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();
}
成功了。我总是乐于改进。
我必须通过一个按钮来同步两个数据库。在按钮下,我在 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();
}
成功了。我总是乐于改进。