2010-01-25 2 views
13

У меня есть следующий код:JScrollPane и JList автопрокрутка

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

Он автоматически прокручивается вниз. Но, если я попытаюсь прокрутить назад, чтобы перечитать сообщение, он запустит прокрутку вниз. Как я могу это исправить?

ответ

10

При добавлении нового сообщения вызывается scrollRectToVisible() на JList с использованием Rectangle с теми же размерами, что и размер вашего сообщения. При вертикальной ориентации может быть удобно сделать предпочтительный размер JScrollPaneJViewport, являющийся интегральным кратным высоте панели сообщений. См. Также: How to Use Scroll Panes.

Приложение: Это убедительное обсуждение Text Area Scrolling также может быть полезно.

-1

Я думаю, что вы хотите, чтобы он прокручивал вниз, когда вы добавляете материал в свой список сообщений, а не на настройку. Так что ваш код может выглядеть следующим образом:

Adjustable sb = messageScrollList.getVerticalScrollBar() 
boolean onBottom = sb.getValue() == sb.getMaximum(); 
// 
// add your message to the JList. 
// 
if(onBottom) sb.setValue(sb.getMaximum()); 

В противном случае вам нужно будет сказать, если корректировка была вызвана изменением модели, или с помощью мыши, и, глядя через API Docs Я не уверен, если есть способ сделать это легко. Хотя вы могли видеть, возвращает ли AdjustmentEvent.getAdjustmentType() разные значения в этих случаях, если это правда, вы можете просто иметь оператор if в своем анонимном внутреннем классе.

Еще одна вещь, которую вы могли бы попробовать, заключалась бы в том, чтобы иметь логическую переменную где-нибудь, которая устанавливается, когда вы добавляете что-то в список. Затем в вашем обработчике вы проверяете, установлена ​​ли переменная. Если это так, вы выполняете настройку (и отключите переменную) в противном случае, вы игнорируете ее. Таким образом, в список будет добавлен только один прокрутка вниз.

+0

Тип регулировки одинаковый в обоих случаях. Я пробовал это прокручивать вниз, если сообщение добавлено. Но если я это сделаю, последнее добавленное сообщение не будет видно. Он прокручивается недостаточно. Как я могу это решить? – dododedodonl

+0

Хм ... Ну, одна вещь, которую вы могли бы сделать, - иметь где-то булевскую переменную, которая устанавливается, когда вы добавляете что-то в список. Затем в вашем обработчике вы проверяете, установлена ​​ли переменная. Если это так, вы выполняете настройку (и отключите переменную) в противном случае, вы игнорируете ее. Таким образом, в список будет добавлен только один прокрутка вниз. –

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

Я нашел это очень полезно: http://forums.sun.com/thread.jspa?threadID=623669 (сообщение от «inopia»)
Он прекрасно работает

Как он говорит: «Проблема здесь заключается в том, что она может стать немного трудно найти событие, которое срабатывает после того, как обновлены ListModel, JList и JScrollPane. "

+0

Ссылка мертва. Вы можете его обновить? –

0

Для автоматической прокрутки Я использую очень простую концепцию статического переменный и 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++); 
    /* 
    * 
    */ 


    } 
1

@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 и получает свое неотъемлемое поведение.