繁体   English   中英

JScrollPane 和 JList 自动滚动

[英]JScrollPane and JList auto scroll

我有下一个代码:

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

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

添加新消息时,使用与消息窗格的首选大小具有相同尺寸的RectangleJList上调用scrollRectToVisible() 给定垂直方向,将JScrollPaneJViewport的首选大小设为消息窗格高度的整数倍可能会很方便。 另请参阅: 如何使用滚动窗格

附录:这个关于文本区域滚动的引人入胜的讨论也可能会有所帮助。

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

@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)并获得其固有行为。

我发现这真的很有用: http ://forums.sun.com/thread.jspa?threadID=623669('inopia' 发布)
它完美地工作

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

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

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

我认为您想要做的是在将内容添加到 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 语句。

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

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


    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM