【问题标题】:Auto text scroll for text area (JTextArea) with caret position set to the beginning of the last line文本区域 (JTextArea) 的自动文本滚动,插入符号位置设置为最后一行的开头
【发布时间】:2012-05-28 01:45:41
【问题描述】:

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

这是我用来设置它的代码 sn-p。

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

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

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

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

【问题讨论】:

    标签: java swing jtextarea caret autoscroll


    【解决方案1】:

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

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

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

    【讨论】:

    • 很酷的解决方案!但我在这里有一个问题。有什么办法可以设置 ta.setCaretPosition(ta.getLineStartOffset(ta.getLineCount() - 1));只有一次,而不是每次都更新它,以便它对整个应用程序保持有效?
    • 此外,虽然您使用的是 DefaultCaret caret = (DefaultCaret) ta.getCaret();caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);如果没有这些语句,您的代码也可以工作吗?您对此有何看法?
    • @JtheRocker 不是我知道的。随着文本的更新,插入符号的位置会不断移动。因此,这意味着每次都需要重新计算其位置。您可以通过首先调用 super.setText 然后定位插入符号来扩展 JTextArea 并覆盖 setText。至于你的第二个问题,这是一个期望行为和人体工程学的问题。在您的问题中,这就是您所要求的。现在,如果您正在查看实际滚动到滚动窗格的左下角,那么您正在寻找其他东西。如果是这样,请考虑在 SO 上发布另一个问题。
    猜你喜欢
    • 2013-05-21
    • 2020-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-14
    • 2011-05-26
    相关资源
    最近更新 更多