Java Swing: Подход для динамического добавления текста в текстовую область, обновление полосы прокрутки - PullRequest
5 голосов
/ 12 июня 2009

Каков общий подход с Java swing для обновления текстовой области со строками текста (скажем, из потока), а затем для перемещения текстового каретки в конец текстовой области по мере добавления текста. Также обновите полосу прокрутки, чтобы она была внизу.

Я думал, что у меня будет буфер строк и добавлю к нему текст, а затем установлю строку в текстовой области и расположу полосу прокрутки внизу.

Ответы [ 5 ]

13 голосов
/ 12 июня 2009

Используйте append() для добавления текста, затем setCaretPosition(), чтобы убедиться, что вы прокручиваете его.

myTextPane.append(textFromSomewhere);
myTextPane.setCaretPosition(myTextPane.getDocument().getLength());
7 голосов
/ 12 июня 2009

Метод append () не делает то, что вы хотите?

И хотя вы не спрашивали: когда вы генерируете что-то в фоновом потоке, обязательно используйте SwingUtilities.invokeLater () для обновления ваших компонентов.

3 голосов
/ 12 июня 2009

Из другого потока вы должны использовать java.awt.EventQueue.invokeLater, чтобы войти в EDT, и тогда все работает.

Итак:

java.awt.EventQueue.invokeLater(new Runnable() { public void run() {
    Document doc = text.getDocument();
    int origLen = doc.getLength()
    try {
        doc.insertString(origLen, msg, null);
    } catch (BadLocationException exc) {
        // Odd APIs forces us to deal with this nonsense.
        IndexOutOfBoundsException wrapExc = new IndexOutOfBoundsException();
        wrapExc.initCause(exc);
        throw wrapExc;
    }
    // IIRC, Position is a bit odd and 
    if (origLen == 0) {
        text.setCaretPosition(doc.getLength());
    }
}});

Если кто-нибудь прочитает документацию по API для JTextArea.append, он заявляет, что является поточно-ориентированным. JDK7 удаляет эту маловероятную претензию (напоминание: многопоточность трудна). Как правило, в Swing я склонен всегда идти прямо к модели / Document.

Я считаю, что если каретка в конце, она должна быть перенесена после добавления. Единственное исключение, если нет текста, из-за странного API. Если он был перемещен, то мы, вероятно, не хотим обновлять его после добавления.

Примечание: если несколько потоков делают это, вы не обязательно знаете, что получится первым.

1 голос
/ 01 июля 2012

Вы можете обновить полосу прокрутки без чтения длины документа с помощью:

scrollbar.setValue(scrollbar.getMaximum());

Обновление (позже добавлено в Invoke, код от Tom Hawtin)

java.awt.EventQueue.invokeLater(new Runnable() { public void run() {
    try {
        textArea.append(msg);
    } catch (BadLocationException exc) {
        // Odd APIs forces us to deal with this nonsense.
        IndexOutOfBoundsException wrapExc = new IndexOutOfBoundsException();
        wrapExc.initCause(exc);
        throw wrapExc;
    }
    JScrollBar bar = scrollPane.getVerticalScrollBar();
    bar.setValue(bar.getMaximum());
}});
1 голос
/ 12 июня 2009

Если вы обновляете из потока, не забудьте использовать SwingWorker или какой-либо другой подход AWT, ориентированный на поток.

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