Я пытаюсь имитировать функциональность Adium и большинства других клиентов чата, которые я видел, причем полосы прокрутки продвигаются вниз, когда приходят новые сообщения, но только если вы уже там. Другими словами, если вы прокрутили несколько строк вверх и читаете, то, когда приходит новое сообщение, оно не переместит вашу позицию в нижнюю часть экрана; это было бы раздражающим. Но если вы прокрутите до конца, программа справедливо предполагает, что вы хотите видеть самые свежие сообщения в любое время, и поэтому автоматически выполняет прокрутку.
У меня был медведь времени, пытающийся подражать этому; платформа, кажется, борется с этим поведением любой ценой. Лучшее, что я могу сделать, это:
В конструкторе:
JTextArea chatArea = new JTextArea();
JScrollPane chatAreaScrollPane = new JScrollPane(chatArea);
// We will manually handle advancing chat window
DefaultCaret caret = (DefaultCaret) chatArea.getCaret();
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
В методе, который обрабатывает новый текст:
boolean atBottom = isViewAtBottom();
// Append the text using styles etc to the chatArea
if (atBottom) {
scrollViewportToBottom();
}
public boolean isAtBottom() {
// Is the last line of text the last line of text visible?
Adjustable sb = chatAreaScrollPane.getVerticalScrollBar();
int val = sb.getValue();
int lowest = val + sb.getVisibleAmount();
int maxVal = sb.getMaximum();
boolean atBottom = maxVal == lowest;
return atBottom;
}
private void scrollToBottom() {
chatArea.setCaretPosition(chatArea.getDocument().getLength());
}
Так вот, это работает, но затрапезно и не идеально по двум причинам.
- При установке позиции каретки любой выбор пользователя в области чата стирается. Я могу себе представить, что это будет очень раздражающим, если он пытается скопировать / вставить.
- Поскольку продвижение панели прокрутки происходит после вставки текста, есть доля секунды, когда полоса прокрутки находится в неправильном положении, а затем она визуально скачет к концу. Это не идеально.
Прежде чем вы спросите, да, я прочитал этот пост в блоге на Прокрутка текстовой области , но прокрутка по умолчанию не соответствует желаемому.
Другие связанные (но, на мой взгляд, не совсем полезные) вопросы:
Настройка полосы прокрутки на панели jscroll
Автоматическая прокрутка JScrollPane до упора.
Любая помощь в этом отношении будет очень признательна.
Edit:
Согласно совету Devon_C_Miller, у меня есть улучшенный способ прокрутки до дна, решения проблемы № 1.
private void scrollToBottom() {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
int endPosition = chatArea.getDocument().getLength();
Rectangle bottom = chatArea.modelToView(endPosition);
chatArea.scrollRectToVisible(bottom);
}
catch (BadLocationException e) {
System.err.println("Could not scroll to " + e);
}
}
});
}
У меня все еще есть проблема # 2.