Я пытаюсь подражать функциональности 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());
}
Теперь, это работает, но это - janky и не идеальное по двум причинам.
Перед выяснением да я считал это сообщение в блоге на Прокрутке Текстовой области, но прокрутка по умолчанию для насыщения поведения не то, что я хочу.
Другое связанное (но по моему мнению, не абсолютно полезный в этом отношении) вопросы: Установка полосы прокрутки на jscrollpane Создание JScrollPane автоматически прокрутить полностью вниз.
Любая справка в этом отношении очень ценилась бы.
Править:
Согласно совету 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.
Взгляните на scrollRectToVisible (Rectangle r) и modelToView (int pos)
Это должно дать вам то, что вы ищете, не мешая выбору пользователя.
Что касается полосы прокрутки, попробуйте принудительно выполнить прокрутку и добавление при разных событиях. Например:
if (atBottom) {
// append new line & do scroll
SwingUtilities.invokerLater(new Runnable(){
public void run() {
// append text
}});
} else {
// append newline
// append text
}
Посмотрите этот пример .
Хотя я бы изменил код, чтобы использовать следующий, который будет более эффективным:
caret.setDot(textArea.getDocument().getLength());