Java: BufferedStreams и обработчики событий - PullRequest
1 голос
/ 14 февраля 2012

Я работаю над «консолью», использующей JTextArea, и все работает отлично, за исключением того, что вывод не работает так, как я хочу.

Я использую модифицированную версию классаЯ нашел здесь в Stackoverflow.

import java.io.*;
import javax.swing.*;

public class textareaStream extends OutputStream {

//*************************
//* Parameters
//*************************
private JTextArea textArea; // target text area
private byte[] aByte;     // array for write(int val);

//*************************
//* Constructor
//*************************
public textareaStream(JTextArea ta) {
    textArea=ta;
    aByte=new byte[1];
}


//*************************
//* Writing methods
//*************************
public void write(int val) {
    aByte[0]=(byte)val;
    write(aByte,0,1);
}

public void write(byte[] ba) {
    write(ba,0,ba.length);
}

public synchronized void write(byte[] ba,int str,int len) {
    try {
        for(int xa=0; xa<10; xa++) {
            try {
                textArea.append(new String(ba,str,len));
                break;
            } catch(Throwable thr) {
                if (xa==9) {
                    thr.printStackTrace();
                } else {
                    Thread.sleep(200);
                }
            }
        }
    } catch(Throwable thr) {
        CharArrayWriter caw=new CharArrayWriter();
        thr.printStackTrace(new PrintWriter(caw,true));
        textArea.append(System.getProperty("line.separator","\n"));
        textArea.append(caw.toString());
    }
}
}

Это прекрасно работает, кроме случаев, когда вызывается метод "write" из обработчика событий.

В обработчике событий текст не пишетсяв текстовое поле, пока событие не закончится.Я хочу, чтобы текст записывался на консоль во время выполнения команды (это особенно необходимо для команд, занимающих много времени).Другими словами, когда пользователь нажимает клавишу ввода (например), выполняется длинный процесс при печати данных в JTextArea, но текст не отображается до тех пор, пока после не будет запущен весь процесс.

У кого-нибудь есть идеи, как мне это обойти?

1 Ответ

1 голос
/ 14 февраля 2012

Если я вас правильно понимаю, вы используете свой класс из какого-то обработчика событий и вызываете там метод write. В этом случае вы можете использовать метод SwingUtilities.invokeLater . Смотрите это, например:

http://www.javamex.com/tutorials/threads/invokelater.shtml

По сути, вы бы создали вспомогательный метод по следующим направлениям:

private void writeOnEDT(final byte[] ba, final int str, final int len) {
  SwingUtilities.invokeLater(new Runnable() {
    public void run() {
      instance.write(ba, str, len); 
    }
  });
}

где instance - это экземпляр вашего textareaStream класса. Если вы решите поместить это в тот же класс, просто удалите instance. и используйте writeOnEDT вместо write, он должен работать правильно.

Обратите внимание, что любое длительное задание, которое у вас есть, должно не выполняться в EDT - в противном случае вся активность события будет ждать. Вы можете использовать потоков или исполнителей (см. Также: http://www.baptiste -wicht.com / 2010/09 / java-concurrency-part-7-executors-and- thread-pool / ) для достижения этой цели. Это во многом зависит от проблемы, которую вы пытаетесь решить.

Методы классов Swing GUI всегда должны вызываться в потоке EDT - см., Например, это для подробного объяснения, если вы заинтересованы:

Одна стилистическая вещь - вы назвали свой класс textareaStream. Это фактический стандарт, согласно которому классы Java должны начинаться с заглавной буквы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...