ComiaTip System.out -tulostus tekstikenttään


System.out.print Tekstikenttään

Kirjoittanut Hannu Julkaistu 23.4.2009

Joskus on hyödyllistä ohjata System.out tulostukset muualle kuin komentorivi-ikkunaan. Jollei oma, niin jonkun toisen koodi voi sisältää System.out.println tulostuksia joita ei enää tarvita tai ongelmien selvittelyssä tarpeelliset tulostukset voivat hävitä bittiavaruuteen kun ohjelmaa ei käynnistetäkkään komentoriviltä.

Useimmista - luultavimmin kaikista - ohjelmointikielien standardikirjastoista löytyy käsite stream. Yksinkertaistettuna streamia voidaan lukea tai sitä voidaan kirjoittaa merkki/tavu kerrallaan. Kun javassa käytetään System.out.println("hello world") metodia tulostamaan komentorivi-ikkunaan, niin tulostus kirjoitetaan streamiin System.out josta se päätyy tulostukseksi ikkunaan. System.out vuolle on setter metodi ja oman stream luokan toteutus on yksinkertaista, joten mikään ei estä ohjaamasta System.out tulosteita esimerkiksi JTextArea -komponenttiin.

public class TerminalTextArea extends JTextArea { private OutputStream areaStream; public TerminalTextArea(){ areaStream = new OutputStream(){ @Override public void write(int mark) throws IOException //Poikkeuksellisesti textarean append ON //säieturvallinen append(Character.toString((char)mark )); } }; //tämä pitää tekstikentän skrollattuna kuten //terminaali-ikkunalta oletetaan ((DefaultCaret)this.getCaret()). setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE); } //tekstikenttään kirjoittava OutputStream annetaan //kapseloituna PritStream olioon public PrintStream getNewPrintstream(){ return new PrintStream(areaStream); } }

Ylläolevassa koodinpätkässä on Swingin tekstikenttä komponentista tehty aliluokka, jossa luodaan OutputStream -olio. OutputStreamia kirjoittavat oliot kutsuvat streamin write(int) metodia, joka on tässä toteutettu kutsumaan tekstikentän append metodia. JTextArea componentin append metodi lisää sille parametrina annetun merkin tekstikentän tekstin loppuun.

Write(int) metodin parametri on int tyyppinen siitä syystä, että OutputStream ei ota kantaan siihen onko sen kirjoittama data tavuja (byte) vai merkkejä (char).

Tekstikentän tekstikursorin UpdatePolicy ALWAYS_UPDATE pitää tekstikentän scorllattuna aina viimeiselle riville. Jostakin syystä setUpdatePolicy on nähty hyväksi jättää pois Caret:in rajapinnasta, joten getCaret metodin palauttama Caret täytyy castata DefaultCaret:iksi jotta sen UpdatePolicy:n saa asetettua.

Huomaa että tässä Outputstreamin write -metodia tulee kutsumaan se säie, joka hoitaa tulostuksen eikä Swingin tapahtumankäsittelijäsäie. Yleensä Swing komponentin tilaa saisi muuttaa vain tapahtumankäsittelijäsäie, mutta poikkeuksena suurimmasta osasta Swingin metodeja JTextArea:n append metodin kutsuminen on turvallista tehdä mistä tahansa säikeestä (ks. javan dokumentaatio).

//Luodaan edellä tehty tekstikenttäkomponentti TerminalTextArea terminalTextArea = new TerminalTextArea(); //pyydetään tekstikentältä PrintStream olio ja asetetaan se //System.out ja System.err printstreamien tilalle PrintStream stream = terminalTextArea.getNewPrintstream(); System.setOut(stream); System.setErr(stream);

System.out ja System.err (samanlainen kuin System.out mutta tarkoitettu virheviestien tulostukseen) streamit ovat tyyppiä PrintStream. Tekstikentälle lisätty getNewPrintstream() antaa PrintStream luokan olion, joten se voidaan asettaa System.out ja System.err streamien tilalle.

Kun System.out ja System.err stream on korvattu, ohjelma ei enää tulosta mitään terminaali-ikkunaan vaikka ohjelma käynnistettäisiin komentoriviltä. Pienellä lisäkikkailulla tulostuksen voi kuitenkin saada useampaan streamiin.