Java Swing:在文本区域中动态附加文本的方法,具有滚动条更新

使用Java swing来更新textarea的一般方法是什么,用文本行(比如来自一个Thread),然后在添加文本时将文本插入符号流到textarea的底部。 还要更新滚动条,使其位于底部。

我想我会有一个stringbuffer并将文本追加到那个然后在textarea中设置字符串并将滚动条放在底部。

使用append()添加文本,然后使用setCaretPosition()以确保使用它滚动。

 myTextPane.append(textFromSomewhere); myTextPane.setCaretPosition(myTextPane.getDocument().getLength()); 

append()方法不能做你想要的吗?

虽然您没有问:当您在后台线程中生成某些内容时,请务必使用SwingUtilities.invokeLater()来更新您的组件。

从另一个线程,您应该使用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()); } }}); 

如果有人阅读JTextArea.append的API文档,它声称是线程安全的。 JDK7消除了这种不太可能的声明(提醒:线程很难)。 作为一项规则,在Swing中,我倾向于直接使用模型/ Document

我相信如果插入符号在最后它应该在追加后继续前进。 唯一的例外是如果没有文本,因为奇怪的API。 如果它已被移动,那么我们可能不希望在追加后更新它。

注意:如果多个线程正在执行此操作,则您不一定知道哪个线程会首先到达那里。

如果要从线程更新,请不要忘记使用SwingWorker或其他一些AWT线程安全方法。

您可以在不读取doc.length的情况下更新滚动条:

 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()); }});