可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I've got the next code:
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());
}
});
It auto scrolls down. But, if I try to scroll back up to re-read a message, it forces a scroll down.
How can I fix this?
回答1:
When adding a new message, invoke scrollRectToVisible()
on the JList
using a Rectangle
having the same dimensions as your message pane's preferred size. Given a vertical orientation, it may be convenient to make the preferred size of the JScrollPane
's JViewport
an integral multiple of the message pane's height. See also: How to Use Scroll Panes.
Addendum: This compelling discussion of Text Area Scrolling may be helpful, too.
回答2:
I found this really useful:
http://forums.sun.com/thread.jspa?threadID=623669 (post by 'inopia')
It works perfectly
As he says:
"The problem here is that it can become a bit difficult to find an event that fires after both the ListModel, JList and JScrollPane have been updated."
回答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());
回答4:
@question enquirer. Please change your code from
messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
e.getAdjustable().setValue(e.getAdjustable().getMaximum());
}
});
to
messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
e.getAdjustable().setValue(e.getAdjustable().getValue());
}
});
That is change getMaximum()
to getValue()
Then it works as required. getMaximum()
takes the scroller to its maximum; while getValue()
takes it wherever event happens.
You can avoid using this piece of code altogether if you put one line
messageScrollList.setViewportView(messageList);
That works like add(component)
for jList and gets its inherent behaviour.
回答5:
I think what you want to do is have it scroll down when you add stuff to your messageList, rather then on adjustment. So your code could look like this:
Adjustable sb = messageScrollList.getVerticalScrollBar()
boolean onBottom = sb.getValue() == sb.getMaximum();
//
// add your message to the JList.
//
if(onBottom) sb.setValue(sb.getMaximum());
Otherwise you would need to tell if the adjustment was caused by a model change, or by the mouse, and looking through the API docs I'm not sure if there's a way to do that easily. Although you could see if the AdjustmentEvent.getAdjustmentType()
returns different values in those cases, if that's true then you could just have an if statement in your anonymous inner class.
Another thing you could try would be to have a boolean variable somewhere that gets set when you add something to the list. Then, in your handler you check to see if the variable is set. If so, you do the adjustment (and unset the variable) otherwise, you ignore it. That way, there will be only one scroll-down per item being added to the list.
回答6:
I used JScrollPane
with JTextArea
. I avoided force scroll down by scrolling only when JScrollBar max
value changed:
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();
});
I suppose, there is better solution to filter events without extra variables, and would appreciate if somebody post it.
回答7:
To auto scroll I am using a very simple concept of static variable and 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++);
/*
*
*/
}