14

我有下一个代码:

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

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

4

7 回答 7

10

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

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

于 2010-01-25T17:24:12.903 回答
3
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());
于 2010-03-31T17:26:57.690 回答
1

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

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

于 2010-06-15T04:54:25.187 回答
1

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

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()Then 它可以根据需要工作。getMaximum()将滚动条发挥到最大;whilegetValue()将它带到任何事件发生的地方。

如果你放一行,你可以完全避免使用这段代码

messageScrollList.setViewportView(messageList);

这就像add(component)jList 一样工作并获得其固有的行为。

于 2014-03-31T00:06:41.353 回答
1

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

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

于 2018-09-27T14:37:32.140 回答
0

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

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

于 2010-01-25T13:27:08.727 回答
-1

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


    }
于 2013-11-06T07:22:18.103 回答