Swing:滚动到JScrollPane的底部,以当前视口位置为条件 [英] Swing: Scroll to bottom of JScrollPane, conditional on current viewport location

查看:152
本文介绍了Swing:滚动到JScrollPane的底部,以当前视口位置为条件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图模仿Adium和我见过的大多数其他聊天客户端的功能,其中当新消息进入时滚动条会向前移动,但前提是你已经在那里。换句话说,如果你向上滚动几行并正在阅读,当有新消息进入时它不会将你的位置跳到屏幕的底部;这会很烦人。但如果您滚动到底部,程序会正确地假设您希望始终查看最新的消息,因此会自动滚动。

I am attempting to mimic the functionality of Adium and most other chat clients I've seen, wherein the scrollbars advance to the bottom when new messages come in, but only if you're already there. In other words, if you've scrolled a few lines up and are reading, when a new message comes in it won't jump your position to the bottom of the screen; that would be annoying. But if you're scrolled to the bottom, the program rightly assumes that you want to see the most recent messages at all times, and so auto-scrolls accordingly.

I有一段时间试图模仿这个;该平台似乎不惜一切代价来对抗这种行为。我能做的最好的事情如下:

I have had a bear of a time trying to mimic this; the platform seems to fight this behavior at all costs. The best I can do is as follows:

在构造函数中:

JTextArea chatArea = new JTextArea();
JScrollPane chatAreaScrollPane = new JScrollPane(chatArea);

// We will manually handle advancing chat window
DefaultCaret caret = (DefaultCaret) chatArea.getCaret();
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);

处理新文本的方法:

boolean atBottom = isViewAtBottom();

// Append the text using styles etc to the chatArea

if (atBottom) {
    scrollViewportToBottom();
} 


public boolean isAtBottom() {
    // Is the last line of text the last line of text visible?
    Adjustable sb = chatAreaScrollPane.getVerticalScrollBar();

    int val = sb.getValue();
    int lowest = val + sb.getVisibleAmount();
    int maxVal = sb.getMaximum();

    boolean atBottom = maxVal == lowest;
    return atBottom;
}


private void scrollToBottom() {
    chatArea.setCaretPosition(chatArea.getDocument().getLength());
}

现在,这很有效,但由于两个原因,它很笨拙而不理想。 / p>

Now, this works, but it's janky and not ideal for two reasons.


  1. 通过设置插入位置,用户在聊天区域中可能具有的任何选择都将被删除。我可以想象,如果他试图复制/粘贴,这会非常恼人。

  2. 由于滚动窗格的推进发生在插入文本之后,滚动条有一瞬间。在错误的位置,然后它在视觉上跳到最后。这不太理想。

在你提问之前,是的我已经在文本区域滚动,但默认滚动到底部行为不是我想要的。

Before you ask, yes I've read this blog post on Text Area Scrolling, but the default scroll to bottom behavior is not what I want.

其他相关(但在我看来,在这方面并不完全有用)问题:
在jscrollpane上设置滚动条
让JScrollPane自动向下滚动。

Other related (but to my mind, not completely helpful in this regard) questions: Setting scroll bar on a jscrollpane Making a JScrollPane automatically scroll all the way down.

这方面的任何帮助非常感谢。

Any help in this regard would be very much appreciated.

编辑:

根据Devon_C_Miller的建议,我有一种改进的滚动方式到底,解决问题#1。

As per Devon_C_Miller's advice, I have an improved way of scrolling to the bottom, solving issue #1.

private void scrollToBottom() {
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
       public void run() {
           try {
               int endPosition = chatArea.getDocument().getLength();
               Rectangle bottom = chatArea.modelToView(endPosition);
               chatArea.scrollRectToVisible(bottom);
           }
           catch (BadLocationException e) {
               System.err.println("Could not scroll to " + e);
           }
       }
    });
}

我仍有问题#2。

推荐答案

看一下 scrollRectToVisible(Rectangle r) modelToView(int pos)

那应该能得到什么你正在寻找而不会打扰用户的选择。

That should get you what you're looking for without disturbing the user's selection.

对于滚动条,尝试强制滚动并在不同事件上发生追加。例如:

As for the scrollbar, try forcing the scroll and the append into occur on different events. For example:

if (atBottom) {
    // append new line & do scroll
    SwingUtilities.invokerLater(new Runnable(){
        public void run() {
            // append text
        }});
} else {
    // append newline
    // append text
}

这篇关于Swing:滚动到JScrollPane的底部,以当前视口位置为条件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆