Java JScrollPane和JList自动滚动
我有下一个代码:Java JScrollPane和JList自动滚动,java,swing,jscrollpane,jlist,autoscroll,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 JScrollPan
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());
}
});
它会自动向下滚动。但是,如果我试图向上滚动以重新阅读邮件,则会强制向下滚动。
我该如何解决这个问题?我想你要做的是,当你向消息列表中添加内容时,让它向下滚动,而不是调整。因此,您的代码可以如下所示:
Adjustable sb = messageScrollList.getVerticalScrollBar()
boolean onBottom = sb.getValue() == sb.getMaximum();
//
// add your message to the JList.
//
if(onBottom) sb.setValue(sb.getMaximum());
否则,您需要知道调整是由模型更改引起的,还是由鼠标引起的,并且查看API文档,我不确定是否有办法轻松做到这一点。虽然您可以看到在这些情况下是否返回不同的值,但如果是这样,那么您可以在匿名内部类中使用if语句
您可以尝试的另一件事是在某个地方设置一个布尔变量,当您向列表中添加某些内容时,该变量将被设置。然后,在处理程序中检查变量是否已设置。如果是这样,则进行调整(并取消设置变量),否则忽略它。这样,添加到列表中的每个项目只有一次向下滚动。添加新邮件时,请使用与邮件窗格首选大小相同的尺寸在上调用。给定垂直方向,可以方便地将的首选大小设置为消息窗格高度的整数倍。另见:
附录:这一引人注目的讨论可能也很有帮助。我发现这一点非常有用:
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());
(由“inopia”发布)它工作得很好 正如他所说:
“这里的问题是,在更新ListModel、JList和JScrollPane之后,要找到触发的事件可能会有点困难。”要自动滚动,我使用了一个非常简单的静态变量和list.makeVisible(int index)概念
@询问者。请从更改您的代码
messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
e.getAdjustable().setValue(e.getAdjustable().getMaximum());
}
});
到
也就是说,将getMaximum()
更改为getValue()
,然后它可以根据需要工作getMaximum()
使滚动条达到最大值;而getValue()
会在事件发生的任何地方使用它
如果只放一行代码,就可以避免完全使用这段代码
messageScrollList.setViewportView(messageList);
这就像jList的
add(component)
,并获得其固有行为。我使用JScrollPane
和JTextArea
一起使用。我通过仅在JScrollBar max
值更改时滚动来避免强制向下滚动:
JScrollPane scrollPane=新的JScrollPane(jTextArea);
verticalScrollBarMaximumValue=scrollPane.getVerticalScrollBar().getMaximum();
scrollPane.getVerticalScrollBar().addAdjustmentListener(
e->{
如果((垂直滚动条最大值-e.getAdjustable().getMaximum())==0)
返回;
e、 getAdjustable().setValue(例如getAdjustable().getMaximum());
verticalScrollBarMaximumValue=scrollPane.getVerticalScrollBar().getMaximum();
}
);
我想,有更好的解决方案可以过滤没有额外变量的事件,如果有人发布它,我们将不胜感激。在这两种情况下,adjustmenttype是相同的。我尝试过在添加消息时向下滚动。但如果我这样做,最后添加的消息将不可见。它向下滚动不够。我该怎么解决呢?嗯。。。嗯,你可以做的一件事是在某个地方设置一个布尔变量,当你向列表中添加一些东西时,它会被设置。然后,在处理程序中检查变量是否已设置。如果是这样,则进行调整(并取消设置变量),否则忽略它。这样,添加到列表中的每个项目只有一个向下滚动。链接已关闭。你能刷新一下吗?
messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
e.getAdjustable().setValue(e.getAdjustable().getValue());
}
});
messageScrollList.setViewportView(messageList);