Ajuda com um JTextArea especial

9 respostas
javakid

bom dia a todos,

estou tentando passar minhas saídas padrão para o meu JTextArea...
mas por sinal eu to travadão em como o meu JtextArea pode disponibilizar meus prints...

como faço para que meu setOut e meu setErr envie suas mensagens através do JTextArea ?
vou precisar do pacote java.io ?

olhem meu codigo:

public class Console extends JFrame {

	JTextArea textArea = new JTextArea();
	PrintStream out;
	PrintStream err;

	public Console(){

		System.setOut(out);
		System.setErr(err);
		
		getContentPane().add(new JScrollPane(textArea));
		setVisible(true);
		setBounds(200,200,500,200);
		
	}
	
	public static void main(String []args){
		new Console();
		System.out.println("testando...");
	}

}

muito obrigado desde já

9 Respostas

ViniGodoy

Essa é uma clase útil para redirecionar um Writer para um TextComponent qualquer.

Mas como vc quer um Stream, veja o post ali debaixo.

public class TextComponentWriter extends Writer {
    private StringBuilder buffer = new StringBuilder();
    private Thread bufferThread; 

    private JTextComponent textComponent;
    private boolean autoScroll = true;

    public TextComponentWriter(JTextComponent textComponent) {
        this.textComponent = textComponent;
        Runnable r = new Runnable() {
            public void run() {
                try {
                    while (!Thread.interrupted()) {
                        writeBuffer();
                        Thread.sleep(100);
                    }
                }
                catch (InterruptedException e) {}
                writeBuffer();
            }
        };
        bufferThread = new Thread(r, "TextComponentWriter Thread");
        bufferThread.setDaemon(true);
        bufferThread.start();
    }

    @Override
    public void write(final int b) throws IOException {        
        write(new char[] {(char) b}, 0, 1);
    }

    @Override
    public synchronized void write(char[] cbuf, int off, int len) 
    throws IOException {
        buffer.append(cbuf, off, len);
    }

    private synchronized void writeBuffer() {
        if (buffer.length() == 0)
            return;
        
        final String str = buffer.toString();
        buffer = new StringBuilder();

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                if (isAutoScroll())
                    textComponent.setCaretPosition(textComponent.getDocument().getLength());
                else if (textComponent.getCaretPosition() == textComponent.getDocument().getLength()
                        && textComponent.getDocument().getLength() > 0)
                    textComponent.setCaretPosition(textComponent.getDocument().getLength() - 1);

                try {
                    textComponent.getDocument().insertString(
                            textComponent.getDocument().getLength(), str, null);
                }
                catch (BadLocationException e) {
                    //Faça o log da exceção aqui
                }
            }
        });
    }

    @Override
    public void flush() {}

    @Override
    public void close() {
        bufferThread.interrupt();
    }

    public boolean isAutoScroll()
    {
        return autoScroll;
    }

    public void setAutoScroll(boolean autoScroll)
    {
        this.autoScroll = autoScroll;
    }
    
    @Override
    protected void finalize() throws Throwable {
        close();
    }
}

Esse worker thread torna o stream mais eficiente, caso o seu documento seja colorido. Descobrimos que o JTextArea não funciona lá tão bem assim nesses casos.

ViniGodoy

Sorry, a classe de cima não serve. Ela serve para outros tipos de output.

Use essa aqui no lugar:
public class TextComponentStream extends OutputStream {
    private JTextComponent textComponent;
    private Style error;

    public TextComponentStream(JTextComponent textComponent, Style error) {
        this.textComponent = textComponent;
        this.error = error;
    }
    
    public void println(String text) {
        print(text + "\n");
    }
    
    public void print(String text) {
        try {
            write(text.getBytes());
        }
        catch (IOException e) {
            //Faça o log da exceção aqui
        }
    }
    
    @Override
    public void write(final int b) throws IOException {
        write(new byte[] {(byte) b}, 0, 1);
    }

    @Override
    public void write(final byte[] b, final int off, final int len) 
    throws IOException {
        final String str = new String(b, off, len);

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    textComponent.getDocument().insertString(
                            textComponent.getDocument().getLength(), str, error);
                }
                catch (BadLocationException e) {
                    //Faça o log da exceção aqui
                }
            }
        });
    }

    @Override
    public void flush() {}

    @Override
    public void close() {}    
}
O uso é assim:
public Style getErrorStyle()
    {
        Style style = getTxtPane().getStyledDocument().addStyle("error",
                null);
        StyleConstants.setForeground(style, Color.red);

        return style;
    }


//Mais tarde...
System.setOut(new TextComponentStream(getTxtPane(), null));
System.setErr(new TextComponentStream(getTxtPane(), getErrorStyle());

Se você usar um JTextPane ao invés de um JTextArea. Os erros saem em vermelho. :)

javakid

que parametro eu uso, pra passar pra esse erro ??

public TextComponentStream(JTextComponent textComponent, Style error) { this.textComponent = textComponent; this.error = error; }

vixi cara… peraí que to me embananando com esse codigo :? hehehe

ViniGodoy

Dá um refresh aí e olha o post ali em cima.
Eu tava editando justamente isso. :slight_smile:

javakid

ok… vou respirar agora…
heheeh… olhar calmamamente…

ViniGodoy

Essas duas classes são excelentes para se ter na manga.
Tente usar elas “de fora”… e mais tarde, se quiser, tente entende-las.

Se vc nunca lidou com Documents no Java, dá uma olhada no tutorial do GUJ chamado “Controlando um TextField”.

javakid

OK, obrigado colega!

:wink:

C

Caro viniGodoy

Me desculpe se estou sendo ignorante, mas os métodos: System.setOut() e System.setErr() pedem como parâmetro um objeto tipo PrintStream, e a classe TextComponentStream é do tipo OutputStream.

Tem que fazer um cast nesse caso?

ViniGodoy

System.setOut(new PrintStream(new TextComponentStream(seuTextPane, false)); System.setErr(new PrintStream(new TextComponentStream(seuTextPane, true));

Criado 29 de fevereiro de 2008
Ultima resposta 28 de out. de 2008
Respostas 9
Participantes 3