views:

1066

answers:

5

Hi All,

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?

A: 

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.

Chad Okere
The adjustmenttype is the same in both cases. I've tried this to scroll down if an message is added. But if I do that, the last added message isn't visible. It scrolls not enough down. How can I solve that?
dododedodonl
Hmm... Well, one thing you could do 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.
Chad Okere
+3  A: 

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.

trashgod
A: 

I still can't get the solution out of it... the scrollpane forces to scroll down and can't stay at the point which i want the scroll bar to stop.

kahyee
A: 

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

Gene De Lisa
+1  A: 

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."

mohsenof