I have to synchronise two databases via a button. Under the Button I have a JTextPane in a JScrollPanel. My TextPane class looks like:
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();
}
}
}
The "TextPane" is added to SOUTH in the GUI.
Now I have a few classes which do:
private static final InfoArea ia = InfoArea.getInfoArea();
First I initialise the database connections. Because this is done very fast, the infos are shown at once. But then I do something like this:
private void doSmth() {
for(int i = 0; i < smth; ++i) {
if(sync()) ia.showInfo("OK");
else ia.showInfo("Not OK");
}
}
In other classes it could be a while on a resultset. The Problem is, the textpane is not updated until every method runs trough. I red about this behaviour and I know the problem is with the Event Dispatcher Thread (EDT). I tried to update the showInfo(String msg) as following:
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();
}
}
});
}
But this does not do the trick. I also tried SwingWorker with overriding doInBackground(), publish() and process() but also no success. I also tried a worker thread instead of SwingUitilities. Last I tried:
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");
}
});
}
}
No success. Also I believe this try is the worst, because it blocks the EDT.
As you might notice, I am a bit desperate at the moment because I do not know where to look else. And sorry for not posting all the tries with SwingWorker and WorkerThreads, but they would blow up this post. And it is large enough already.
Can someone tell me, what I have to do to get it working? I need it for a customer who want see something while the synchronisation process is running. I am also willing to provide more info, if something is missing.
Solved it myself. I misunderstood some articles I red yesterday. The solution is, to put the whole task in a thread, not just the method which outputs.
As I said, I click a button to start the synchronisation process. The button calls just a method:
public void syncDB() {
ia.showInfo("Sync cat...");
doCatSync();
ia.showInfo("Sync item...");
doItemSync();
...
}
Now I have to wrap a thread around the tasks:
public void syncDB() {
new Thread() {
public void run() {
ia.showInfo("Sync cat...");
doCatSync();
ia.showInfo("Sync item...");
doItemSync();
...
}
}.start();
}
That did the trick. I am always open for improvements.