JScrollPane和JList自动滚动

时间:2010-01-25 13:11:02

标签: java swing jscrollpane jlist autoscroll

我有下一个代码:

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

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

7 个答案:

答案 0 :(得分:10)

添加新邮件时,使用与邮件窗格首选大小尺寸相同的scrollRectToVisible()JList上调用Rectangle。给定垂直方向,可以方便地使JScrollPaneJViewport的首选大小成为消息窗格高度的整数倍。另见:How to Use Scroll Panes

附录:对Text Area Scrolling这一引人注目的讨论也可能有所帮助。

答案 1 :(得分:1)

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

答案 2 :(得分:1)

我发现这非常有用: http://forums.sun.com/thread.jspa?threadID=623669(由'inopia'发表)
它完美地运作

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

答案 3 :(得分:1)

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

对于jList,它的作用类似add(component),并获得其固有的行为。

答案 4 :(得分:0)

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


    }

答案 5 :(得分:0)

我将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 :(得分:-1)

我认为您要做的是在向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语句。

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