java 文本区域 (JTextArea) 的自动文本滚动,插入符号位置设置为最后一行的开头

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10687281/
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-31 02:06:50  来源:igfitidea点击:

Auto text scroll for text area (JTextArea) with caret position set to the beginning of the last line

javaswingjtextareacaretautoscroll

提问by SSaikia_JtheRocker

I have a simple Java question here. I want to auto text scroll to the beginning of the last line of a text area created using JTextArea. The amount of text per line of the text area is quite longer than the width of the text area.

我在这里有一个简单的 Java 问题。我想将文本自动滚动到使用 JTextArea 创建的文本区域的最后一行的开头。文本区域每行的文本量远大于文本区域的宽度。

Here is the code snippet I used to set that up.

这是我用来设置它的代码片段。

JTextArea textArea = new JTextArea();
DefaultCaret caret = (DefaultCaret)textArea.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);

The problem now is, with the above code, the default behavior is that the caret is auto positioned to the end of the document, as a result, the beginning part of the whole text area gets out of scope. I'd prefer the auto scroll to happen to the beginning of the last line in the document.

现在的问题是,对于上面的代码,默认行为是插入符号自动定位到文档的末尾,因此,整个文本区域的开头部分超出了范围。我希望自动滚动发生在文档最后一行的开头。

To make it clear, here are two screen shots,

为了清楚起见,这里有两个屏幕截图,

What I want is the first one but what's happening is the second one.

我想要的是第一个,但正在发生的是第二个。

What I want is thisWhat I get is this

我想要的是这个我得到的是这个

采纳答案by Guillaume Polet

Simply move the caret to the correct location using getLineCountand getLineStartOffsetafter updating the text of the textarea.

使用getLineCountgetLineStartOffset更新 textarea 的文本后,只需将插入符号移动到正确的位置。

Here is a working example illustrating your desired behaviour:

这是一个说明您想要的行为的工作示例:

import java.util.List;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultCaret;

public class Test {

    private JFrame frame;
    private JTextArea ta;

    protected void initUI() {
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ta = new JTextArea();
        DefaultCaret caret = (DefaultCaret) ta.getCaret();
        caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
        frame.add(new JScrollPane(ta));
        frame.setSize(400, 200);
        frame.setVisible(true);
        new UpdateText().execute();
    }

    class UpdateText extends SwingWorker<String, String> {

        @Override
        public String doInBackground() {
            for (int i = 0; i < 1000; i++) {
                publish("Hello-" + i);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            return null;
        }

        @Override
        public void process(List<String> chunks) {
            for (String s : chunks) {
                if (ta.getDocument().getLength() > 0) {
                    ta.append("\n");
                }
                ta.append(s);
            }
            try {
                ta.setCaretPosition(ta.getLineStartOffset(ta.getLineCount() - 1));
            } catch (BadLocationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        @Override
        public void done() {

        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new Test().initUI();
            }
        });
    }

}