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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/983498/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 14:41:12  来源:igfitidea点击:

Java Swing: Approach for dynamically appending text in text area, have scrollbar update

javaswing

提问by Berlin Brown

What is the general approach with Java swing to update a textarea with lines of text (say from a Thread) and then have the text caret flow to the bottom of the textarea as text is being added. Also update the scrollbar so that it is at the bottom.

Java Swing 更新带有文本行(例如来自线程)的 textarea 的一般方法是什么,然后在添加文本时让文本插入符号流到 textarea 的底部。同时更新滚动条,使其位于底部。

I was thinking that I would have a stringbuffer and append text to that and then set the string in the textarea and position the scrollbar at the bottom.

我在想我会有一个 stringbuffer 并向其附加文本,然后在 textarea 中设置字符串并将滚动条定位在底部。

回答by Michael Myers

Use append()to add the text, then setCaretPosition()to make sure you scroll with it.

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

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

回答by kdgregory

The append() method doesn't do what you want?

append() 方法不符合您的要求?

And although you didn't ask: when you're generating something in a background thread, be sure to use SwingUtilities.invokeLater() to update your components.

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

回答by Tom Hawtin - tackline

From another thread, you should use java.awt.EventQueue.invokeLaterto get on the EDT and then everything works.

从另一个线程,您应该使用java.awt.EventQueue.invokeLater进入 EDT,然后一切正常。

So:

所以:

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

Should anyone read the API docs for JTextArea.appendit claims to be thread-safe. JDK7 removes that unlikely claim (reminder: threading is hard). As a rule, in Swing I tend to always go straight for the model/Document.

是否有人阅读 API 文档,因为JTextArea.append它声称是线程安全的。JDK7 删除了这个不太可能的声明(提醒:线程很难)。通常,在 Swing 中,我倾向于总是直奔模型 / Document

I believe if the caret is at the end it should get moved on after an append. The only exception is if there is no text, because of the strange API. If it has been moved, then we probably don't want to update it after the append.

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

Note: If multiple threads are doing this, you don't necessarily know which will get there first.

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

回答by fachexot

You can update the scrollbar without reading doc.length with:

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

scrollbar.setValue(scrollbar.getMaximum());

Update (wrapped into Invoke later, code from Tom Hawtin)

更新(稍后封装到 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());
}});

回答by akf

If you are updating from a Thread, dont forget to use SwingWorkeror some other AWT Thread-safe approach.

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