[英]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());
}
});
它会自动向下滚动。 但是,如果我尝试向上滚动以重新阅读消息,则会强制向下滚动。 我怎样才能解决这个问题?
添加新消息时,使用与消息窗格的首选大小具有相同尺寸的Rectangle
在JList
上调用scrollRectToVisible()
。 给定垂直方向,将JScrollPane
的JViewport
的首选大小设为消息窗格高度的整数倍可能会很方便。 另请参阅: 如何使用滚动窗格。
附录:这个关于文本区域滚动的引人入胜的讨论也可能会有所帮助。
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 都更新后,找到触发的事件会变得有点困难。”
我将JScrollPane
与JTextArea
。 我仅在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.