当前位置: 首页 > 面试题库 >

摆动:滚动到JScrollPane的底部,视当前视口位置而定

常小白
2023-03-14
问题内容

我正在尝试模仿Adium和我所见过的大多数其他聊天客户端的功能,其中,当收到新消息时,滚动条会移至底部,但前提是您已经在其中。换句话说,如果您向上滚动了几行并且正在阅读,那么当收到一条新消息时,它不会将您的位置跳到屏幕底部;那会很烦人。但是,如果您滚动到底部,则该程序正确地假设您想一直查看最新消息,因此将自动滚动。

我曾经有一段时间想模仿这个。该平台似乎不惜一切代价打击这种行为。我能做的最好的事情如下:

在构造函数中:

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

现在,此方法可行,但它过时且不理想,原因有两个。

  1. 通过设置插入标记位置,用户在聊天区域中可能进行的任何选择都将被删除。我可以想象,如果他尝试复制/粘贴,这将非常令人讨厌。
  2. 由于滚动窗格的前进是在插入文本之后发生的,因此会有一秒钟的瞬间,其中滚动条位于错误的位置,然后它在视觉上跳到末尾。这是不理想的。

在您问之前,是的,我已经阅读了有关Text Area
Scrolling的
博客文章,但是默认滚动至底部行为不是我想要的。

在这方面的任何帮助将不胜感激。

编辑:

按照Devon_C_Miller的建议,我有一种改进的滚动到最底端的方法,解决了问题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)

这应该可以为您提供所需的东西而不会打扰用户的选择。

至于滚动条,请尝试在不同事件上强制进行滚动和追加操作。例如:

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


 类似资料:
  • 问题内容: 我需要将JScrollPane滚动到底部。JScrollPane包含一个JPanel,其中包含许多JLabel。 要滚动到顶部,我只需要: 但是如何精确滚动到最底端?(太远了,它抖动) 问题答案:

  • 我有一个和一个,它由一个带有不同高度项的适配器支持。有没有办法告诉设置滚动位置,使项目X(或多或少)准确地出现在屏幕底部?

  • 我正在研究一个相当复杂的布局。有两个区域(红色和蓝色)必须同时垂直滚动,但右侧区域(蓝色)必须能够独立于其他区域水平滚动。 我设法做到了这一点,但是滚动条总是在的底部,我需要滚动条总是在视口的底部可见。 用HTML/CSS可以做到这一点吗?什么简单的JS或jQuery插件可以帮助实现这一点? 小工具演示

  • 问题内容: 我有一个“浮动工具箱”-的div 。效果很好。 但是,当在该框内滚动(使用鼠标滚轮)并到达底部或顶部时,父元素将“接管”“滚动请求”:工具箱后面的文档将滚动。 -这很烦人,而不是用户的“要求”。 我正在使用jQuery,并认为可以使用event.stoppropagation()停止此行为: 它确实输入了该函数,但是仍然会发生传播(文档滚动) 很难在SO(和Google)上搜索此主题,

  • 问题内容: 我正在使用Ajax请求创建聊天,并且试图使消息div滚动到底部没有太多运气。 我将所有内容包装在这个div中: 有没有一种方法可以使用JS将其默认滚动到底部? 有没有一种方法可以在ajax请求后将其滚动到底部? 问题答案: 这是我在网站上使用的内容:

  • 在我的一个活动中有一个父容器,它调用由一个水平scrollview组成的子容器作为对象之一。有点像recyclerview,其中放置了行对象,有一个由水平滚动视图组成的公共行/项布局。 我的目标是同步horizontalscrollview的位置,这样,当我在其中一个对象上从位置1水平滚动到位置2时,包含HorizonalScrollview的所有其他项目都会从位置1更新到位置2。 这是我的主容器