JScrollPane 和 JList 自动滚动

Posted

技术标签:

【中文标题】JScrollPane 和 JList 自动滚动【英文标题】:JScrollPane and JList auto scroll 【发布时间】:2011-01-09 02:24:32 【问题描述】:

我得到了下一个代码:

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

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

【问题讨论】:

【参考方案1】:

添加新消息时,在JList 上调用scrollRectToVisible(),并使用与消息窗格首选大小相同的Rectangle。给定垂直方向,将JScrollPaneJViewport 的首选大小设置为消息窗格高度的整数倍可能会很方便。另见:How to Use Scroll Panes

附录:关于Text Area Scrolling 的引人注目的讨论也可能会有所帮助。

【讨论】:

【参考方案2】:
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());

【讨论】:

【参考方案3】:

我发现这非常有用: http://forums.sun.com/thread.jspa?threadID=623669('inopia' 发布) 效果很好

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

【讨论】:

链接已失效。可以刷新一下吗?【参考方案4】:

@question 询问者。请从

更改您的代码
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);

这就像 add(component) 用于 jList 并获得其固有的行为。

【讨论】:

【参考方案5】:

我将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();
    
);

我想,有更好的解决方案来过滤没有额外变量的事件,如果有人发布它会很感激。

【讨论】:

【参考方案6】:

我认为您想要做的是在向 messageList 添加内容时让它向下滚动,而不是在调整时向下滚动。所以你的代码可能看起来像这样:

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 语句。

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

【讨论】:

两种情况下的调整类型相同。如果添加了消息,我已经尝试向下滚动。但如果我这样做,最后添加的消息将不可见。它向下滚动不够。我该如何解决? 嗯...好吧,您可以做的一件事是在某处设置一个布尔变量,当您将某些内容添加到列表中时该变量会被设置。然后,在您的处理程序中检查变量是否已设置。如果是这样,您进行调整(并取消设置变量),否则,您将忽略它。这样,每个被添加到列表中的项目只会有一个向下滚动。【参考方案7】:

为了自动滚动,我使用了一个非常简单的静态变量概念和 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++);
     /*
     *
     */


    

【讨论】:

以上是关于JScrollPane 和 JList 自动滚动的主要内容,如果未能解决你的问题,请参考以下文章

java swing中jList滚动条位置问题

Java中Swing组件中的JTextArea,JList控件中的滚动条问题?帮忙解决!

使 JScrollPane 自动向下滚动

Java / Swing:JScrollPane中的JTextArea,如何防止自动滚动?

Swing自定义JScrollPane的滚动条设置,重写BasicScrollBarUI方法

如何使JScrollPane(在BorderLayout中,包含JPanel)平滑自动滚动