Programmieren mit Java
Auf dieser Seite werden Tipps und Tricks zum Arbeiten mit Java dokumentiert.

Konsolenausgabe in TextArea umleiten mit Hilfe von SwingWorker

Szenario:
Eine Applikation wurde programmiert und deren Zwischenmeldungen zunächst nur über den System.out.println Befehl auf die Konsole ausgegeben. Jetzt soll die Funktionalität auch einem Benutzer zugänglich gemacht werden. D.h. man braucht ein GUI und es wäre schön, wenn man die Meldungen direkt in einem TextArea anzeigen könnte.

Lösungsansatz:
Am einfachsten wäre es doch, wenn man alle bisherigen System.out.println Befehle einfach so lassen könnte und die Ausgabe einfach umleiten könnte. Den Hinweis für diese Vorgangsweise und wie man das umsetzt habe ich hier gefunden.

  1. Man schreibt eine Klasse die von der Klasse OutputStream vererbt und überschreibt die Methode public void write(int b) throws IOException mit folgendem Inhalt.

              // redirects data to the text area
              m_pTextArea.append(String.valueOf((char)b));
              
              // scrolls the text area to the end of data
              m_pTextArea.setCaretPosition(m_pTextArea.getDocument().getLength());
              


    (Meine Implementierung kann man hier sehen.)
  2. Beim Start der Funktionalität, die in das TextArea-Element geloggt werden soll, muss der Standard-Output verändert werden. Man sollte sich aber die Standardwerte in einer Variable abspeichern, damit man das wieder zurücksetzen kann.

              myFunctionality(TextAreaOutputStream pOutputStream) {
                //1. redirect the output stream
                PrintStream pStandardOut = System.out;
                if (pOutputStream != null) {
                  PrintStream pPrintStream = new PrintStream(pOutputStream); 
                  System.setOut(pPrintStream);
                }
              
  3. Am Ende der Funktionalität sollte man die Standard Einstellungen wieder herstellen.

                //finally set back the output stream to the default
                System.setOut(pStandardOut);
              } // end of myFunctionality
              
Ab jetzt werden alle Ausgaben, die mit System.out getätigt wurden, in das TextArea Element geschrieben.

Allerdings gibt es einen kleinen Schönheitsfehler: Die Funktionalität läuft voll durch bis die Ausgabe dann als ganzes im TextArea angezeigt wird. Das ist vor allem mühselig, wenn es sich um längere Laufzeiten handelt und somit der Benutzer glaubt, das Programm tut nichts.

Verbesserung:
Damit die Ausgabemeldungen direkt wie bei der Konsole im TextArea Element angezeigt werden, verwende ich einen eigene Klasse, die von der Klasse SwingWorker vererbt. Dabei sind folgende Dinge zu implementieren:
  1. Die Methode doInBackground() muss überschrieben werden und darin sollte die Funktionalität aufgerufen werden, die das Logging in das TextArea Element durchführt. Zusätzlich überprüfe ich hier, ob ein Fehler bei der Funktionalität aufgetreten ist. In diesem Fall wird ein dementsprechendes Flag gesetzt und die Fehlermeldung im GUI ausgegeben.
  2. Die Methode done() sollte überschrieben werden, weil ich dann im Falle der erfolgreichen Ausführung (hier wird der Wert des Flags abgefragt) eine Erfolgsmeldung im GUI ausgebe.
Die Implementierung meiner Klasse kann man sich hier ansehen.