JScrollPane 和 JList 自动滚动

发布于 2024-08-19 06:10:44 字数 677 浏览 10 评论 0 原文

我有下一个代码:

    listModel = new DefaultListModel();
    listModel.addElement(dateFormat.format(new Date()) + ": Msg1");
    messageList = new JList(listModel);
    messageList.setLayoutOrientation(JList.VERTICAL);

    messageScrollList = new JScrollPane(messageList);
    messageScrollList.setPreferredSize(new Dimension(500, 200));

    messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {  
        public void adjustmentValueChanged(AdjustmentEvent e) {  
            e.getAdjustable().setValue(e.getAdjustable().getMaximum());  
        }
    }); 

它自动向下滚动。但是,如果我尝试向上滚动以重新阅读消息,它会强制向下滚动。 我该如何解决这个问题?

I've got the next code:

    listModel = new DefaultListModel();
    listModel.addElement(dateFormat.format(new Date()) + ": Msg1");
    messageList = new JList(listModel);
    messageList.setLayoutOrientation(JList.VERTICAL);

    messageScrollList = new JScrollPane(messageList);
    messageScrollList.setPreferredSize(new Dimension(500, 200));

    messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {  
        public void adjustmentValueChanged(AdjustmentEvent e) {  
            e.getAdjustable().setValue(e.getAdjustable().getMaximum());  
        }
    }); 

It auto scrolls down. But, if I try to scroll back up to re-read a message, it forces a scroll down.
How can I fix this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

捂风挽笑 2024-08-26 06:10:45

我发现这非常有用:
http://forums.sun.com/thread.jspa?threadID=623669 ('inopia' 发表)
正如

他所说:
“这里的问题是,在 ListModel、JList 和 JScrollPane 都更新后,找到触发的事件可能会变得有点困难。”

I found this really useful:
http://forums.sun.com/thread.jspa?threadID=623669 (post by 'inopia')
It works perfectly

As he says:
"The problem here is that it can become a bit difficult to find an event that fires after both the ListModel, JList and JScrollPane have been updated."

如若梦似彩虹 2024-08-26 06:10:45

@问题询问者。请将您的代码从 更改

messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {  
    public void adjustmentValueChanged(AdjustmentEvent e) {  
        e.getAdjustable().setValue(e.getAdjustable().getMaximum());  
    }
});

messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {  
    public void adjustmentValueChanged(AdjustmentEvent e) {  
        e.getAdjustable().setValue(e.getAdjustable().getValue());
    }
}); 

getMaximum() 更改为 getValue() 然后它会按要求工作。 getMaximum() 将滚动条调至最大值;而 getValue() 在事件发生的任何地方都会获取它。

可以完全避免使用这段代码。

messageScrollList.setViewportView(messageList);

如果您放置一行类似于 jList 的 add(component) 的代码并获取其固有行为,则

@question enquirer. Please change your code from

messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {  
    public void adjustmentValueChanged(AdjustmentEvent e) {  
        e.getAdjustable().setValue(e.getAdjustable().getMaximum());  
    }
});

to

messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {  
    public void adjustmentValueChanged(AdjustmentEvent e) {  
        e.getAdjustable().setValue(e.getAdjustable().getValue());
    }
}); 

That is change getMaximum() to getValue() Then it works as required. getMaximum() takes the scroller to its maximum; while getValue() takes it wherever event happens.

You can avoid using this piece of code altogether if you put one line

messageScrollList.setViewportView(messageList);

That works like add(component) for jList and gets its inherent behaviour.

墨小墨 2024-08-26 06:10:45

我将 JScrollPaneJTextArea 一起使用。我仅在 JScrollBar max 值发生变化时才通过滚动来避免强制向下滚动:

JScrollPane scrollPane = new JScrollPane(jTextArea);

verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum();
scrollPane.getVerticalScrollBar().addAdjustmentListener(
    e -> {
        if ((verticalScrollBarMaximumValue - e.getAdjustable().getMaximum()) == 0)
            return;
        e.getAdjustable().setValue(e.getAdjustable().getMaximum());
        verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum();
    }
);

我想,有更好的解决方案来过滤事件而无需额外的变量,如果有人发布它,我将不胜感激。

I used JScrollPane with JTextArea. I avoided force scroll down by scrolling only when JScrollBar max value changed:

JScrollPane scrollPane = new JScrollPane(jTextArea);

verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum();
scrollPane.getVerticalScrollBar().addAdjustmentListener(
    e -> {
        if ((verticalScrollBarMaximumValue - e.getAdjustable().getMaximum()) == 0)
            return;
        e.getAdjustable().setValue(e.getAdjustable().getMaximum());
        verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum();
    }
);

I suppose, there is better solution to filter events without extra variables, and would appreciate if somebody post it.

杯别 2024-08-26 06:10:45

我认为你想要做的是在向消息列表添加内容时让它向下滚动,而不是在调整时滚动。因此,您的代码可能如下所示:

Adjustable sb = messageScrollList.getVerticalScrollBar()
boolean onBottom = sb.getValue() == sb.getMaximum();
//
// add your message to the JList.
//
if(onBottom)  sb.setValue(sb.getMaximum());

否则,您需要判断调整是由模型更改还是由鼠标引起,并查看 API 文档,我不确定是否有办法轻松做到这一点。尽管您可以看到 AdjustmentEvent.getAdjustmentType() 在这些情况下返回不同的值,如果这是真的,那么您可以在匿名内部类中使用 if 语句。

您可以尝试的另一件事是在某处设置一个布尔变量,当您向列表添加某些内容时,该变量会被设置。然后,在处理程序中检查变量是否已设置。如果是这样,则进行调整(并取消设置变量),否则,忽略它。这样,添加到列表中的每个项目只会有一次向下滚动。

I think what you want to do is have it scroll down when you add stuff to your messageList, rather then on adjustment. So your code could look like this:

Adjustable sb = messageScrollList.getVerticalScrollBar()
boolean onBottom = sb.getValue() == sb.getMaximum();
//
// add your message to the JList.
//
if(onBottom)  sb.setValue(sb.getMaximum());

Otherwise you would need to tell if the adjustment was caused by a model change, or by the mouse, and looking through the API docs I'm not sure if there's a way to do that easily. Although you could see if the AdjustmentEvent.getAdjustmentType() returns different values in those cases, if that's true then you could just have an if statement in your anonymous inner class.

Another thing you could try would be to have a boolean variable somewhere that gets set when you add something to the list. Then, in your handler you check to see if the variable is set. If so, you do the adjustment (and unset the variable) otherwise, you ignore it. That way, there will be only one scroll-down per item being added to the list.

最佳男配角 2024-08-26 06:10:45

为了自动滚动,我使用静态变量和 list.makeVisible(int index) 的非常简单的概念

    public class autoScrollExample
    {
     static int index=0;
     private void someFunction()
     /*   
     * 
     */
     list1.add("element1");
     list1.makeVisible(index++);
     /*
     *
     */

     private void someOtherFunction()
     /*   
     * 
     */
     list1.add("element2");
     list1.makeVisible(index++);
     /*
     *
     */


    }

To auto scroll I am using a very simple concept of static variable and list.makeVisible(int index)

    public class autoScrollExample
    {
     static int index=0;
     private void someFunction()
     /*   
     * 
     */
     list1.add("element1");
     list1.makeVisible(index++);
     /*
     *
     */

     private void someOtherFunction()
     /*   
     * 
     */
     list1.add("element2");
     list1.makeVisible(index++);
     /*
     *
     */


    }
丑疤怪 2024-08-26 06:10:44

添加新消息时,调用 scrollRectToVisible() rel="noreferrer">JList 使用 矩形 其尺寸与消息窗格的首选尺寸相同。给定垂直方向,设置 JScrollPaneJViewport 消息窗格高度的整数倍。另请参阅:如何使用滚动窗格

附录:关于文本区域滚动的引人注目的讨论 可能也会有帮助。

When adding a new message, invoke scrollRectToVisible() on the JList using a Rectangle having the same dimensions as your message pane's preferred size. Given a vertical orientation, it may be convenient to make the preferred size of the JScrollPane's JViewport an integral multiple of the message pane's height. See also: How to Use Scroll Panes.

Addendum: This compelling discussion of Text Area Scrolling may be helpful, too.

心安伴我暖 2024-08-26 06:10:44
this.list = blah blah... 
this.list.setSelectedValue(whatever);   
final JScrollPane sp = new JScrollPane(this.list); // needs to be after the parent is the sp 
this.list.ensureIndexIsVisible(this.list.getSelectedIndex());
this.list = blah blah... 
this.list.setSelectedValue(whatever);   
final JScrollPane sp = new JScrollPane(this.list); // needs to be after the parent is the sp 
this.list.ensureIndexIsVisible(this.list.getSelectedIndex());
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文