I have a "ConsoleFrame" which should display my console output in real-time to a JTextArea.
I redirected the output streams:
private void redirectSystemStreams() {
OutputStream out = new OutputStream() {
@Override
public void write(int b) throws IOException {
updateTextArea(String.valueOf((char) b));
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
updateTextArea(new String(b, off, len));
}
@Override
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
};
System.setOut(new PrintStream(out, true));
System.setErr(new PrintStream(out, true));
}
and call the SwingUtilities.invokeAndWait method to append the new text, which works fine
private void updateTextArea(final String text) {
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
txt_console.append(text);
}
});
} catch (InterruptedException ex) {
} catch (InvocationTargetException ex) {
}
}
but it shows me in my new ConsoleFrame this error: java.lang.Error: Cannot call invokeAndWait from the event dispatcher thread and I get that because of the EDT - but why does it work and how can I adapt my code to make it work properly?
invokeAndWait
must be called out of EDT, otherwise caused am exceptions,
carefully with invokeAndWait
, because can freeze whole Swing GUI, locked by exceptions from RepaintManager
(not in all cases only GUI is created, relayout, refreshed some of methods), then applications required restart,
for invokeAndWait
is required to test if (EventQueue.isDispatchThread()) {
/ if (SwingUtilities.isEventDispatchThread()) {
on true you can to setText("")
/ append(""
) without any side effects, output is done on EDT, but is about good practicies to wrap inside invokeLater
use SwingWorker
, there are implemented methods process
, publish
, setProcess
and done
, all mentioned methods notified EDT by default
,
SwingWorker
is designated to run only once time, for repeatly (on some period) to use Executor
for SwingWorker
or Runnable#Thread
as most simple, clear and without any side issues, effects
You can use SwingUtilities.invokeLater()
from any thread, and for error stream it is likely best to use it even when you are already in EDT:
private void updateTextArea(final String text) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
txt_console.append(text);
}
});
}
That particular error you get comes from outside the EDT, and then invokeAndWait()
may be called so you get the output to your console.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.