Автоматическая прокрутка 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());
}
});
он автоматически прокручивается вниз. Но, если я попытаюсь прокрутить назад, чтобы перечитывать сообщение, это заставит прокрутку вниз. Как я могу это исправить?
7 ответов
при добавлении нового сообщения, invoke scrollRectToVisible()
на JList
С помощью Rectangle
имеющие те же размеры, что и предпочтительный размер панели сообщений. Учитывая вертикальную ориентацию, может быть удобно сделать предпочтительный размер JScrollPane
' s JViewport
интегральное кратное высоты панели сообщений. См. также: как использовать прокрутки.
Дополнение: Этого убедительное обсуждение Прокрутка Текстовой Области может быть полезным, тоже.
Я нашел это очень полезным:
http://forums.sun.com/thread.jspa?threadID=623669 (сообщение от 'inopia')
Он отлично работает
как он говорит: "Проблема здесь в том, что может стать немного сложно найти событие, которое срабатывает после обновления ListModel, JList и JScrollPane."
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 enquirer. Пожалуйста, измените код с
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());
}
});
это изменение getMaximum()
to getValue()
затем он работает по мере необходимости. getMaximum()
принимает скроллер на максимум; в то время как getValue()
принимает его везде, где событие происходит.
вы можете избежать использования этого фрагмента кода в целом, если вы поместите одну строку
messageScrollList.setViewportView(messageList);
, работающий add(component)
для jList и получает свое неотъемлемое поведение.
для автоматической прокрутки я использую очень простую концепцию статической переменной и списка.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++);
/*
*
*/
}
Я 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()
возвращает разные значения в этих случаях, если это правда, то вы могли бы просто если заявление в анонимный внутренний класс.
еще одна вещь, которую вы могли бы попробовать, - это иметь логическую переменную, которая устанавливается при добавлении чего-либо в список. Затем в вашем обработчике вы проверяете, установлена ли переменная. Если это так, вы выполняете настройку (и отменяете переменную) в противном случае, вы игнорируете ее. Таким образом, в список будет добавлена только одна прокрутка вниз для каждого элемента.