我有下一个代码:

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

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

有帮助吗?

解决方案

添加新消息时,调用 scrollRectToVisible()JList 用一个 Rectangle 具有与消息窗格的首选大小相同的尺寸。给定垂直方向,可以方便地确定首选尺寸 JScrollPaneJViewport 消息窗格高度的整数倍。也可以看看: 如何使用滚动窗格.

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

其他提示

我发现这真的有用: http://forums.sun.com/thread.jspa?threadID=623669(发布者 'inopia'),点击 它完美

正如他所说: “这里的问题是,它可以成为一个有点难以找到,无论是ListModel的,JList和JScrollPane的火灾后已更新的事件。”

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

add(component)即作品的jList并得到其固有特性。

要自动滚动我使用一个非常简单的静态变量和list.makeVisible(INT指数)的概念

    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++);
     /*
     *
     */


    }

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

我想,有更好的解决办法来过滤事件而无需额外的变量,如果有人后它会升值。

我想你想要做的就是把它向下滚动,当你添加的东西到你给messageManager,而不是在调整什么。所以,你的代码看起来是这样的:

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语句在您的匿名内部类有一个。

另一件事你可以尝试将有一个布尔变量的地方,当你添加了一些列表时设置。然后,在你处理你检查,看是否该变量设置。如果是这样,你做了调整(并取消设置变量),否则,你忽略它。这样一来,会出现只有一个向下滚动每个项目被添加到列表中。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top