Estoy intentando imitar la funcionalidad de Adium y de la mayoría de otros clientes de chat que he visto, donde las barras de desplazamiento avanzan hacia abajo cuando ingresan nuevos mensajes, pero solo si ya estás allí. En otras palabras, si ha desplazado algunas líneas hacia arriba y está leyendo, cuando entra un nuevo mensaje, no saltará su posición hasta la parte inferior de la pantalla; eso sería molesto Pero si se desplaza hacia abajo, el programa correctamente asume que desea ver los mensajes más recientes en todo momento y, por lo tanto, se desplaza automáticamente en consecuencia.Swing: Desplácese hasta la parte inferior de JScrollPane, condicional en la ubicación de la ventana actual
He tenido un mal momento tratando de imitar esto; la plataforma parece luchar contra este comportamiento a toda costa. Lo mejor que puedo hacer es la siguiente:
En constructor:
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);
En método que controla el texto nuevo que entra:
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());
}
Ahora, esto funciona, pero es janky y no es ideal por dos razones.
- Al configurar la posición de intercalación, se borrará cualquier selección que el usuario pueda tener en el área de chat. Me imagino que esto sería muy irritante si está intentando copiar/pegar.
- Dado que el avance del panel de desplazamiento se produce después de insertar el texto, hay una fracción de segundo donde la barra de desplazamiento está en la posición incorrecta, y luego salta visualmente hacia el final. Esto no es ideal
antes de preguntar, sí que he leído esta entrada del blog en Text Area Scrolling, pero el desplazamiento predeterminado a un comportamiento inferior no es lo que quiero.
Otros (pero a mi mente, no del todo útil en este sentido) preguntas relacionadas: Setting scroll bar on a jscrollpane Making a JScrollPane automatically scroll all the way down.
Cualquier ayuda en este sentido sería muy apreciada.
Editar:
De acuerdo con el consejo de Devon_C_Miller, tengo una forma mejorada de desplazarse a la parte inferior, la resolución de la edición # 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);
}
}
});
}
I still have problem # 2.
Puede comprobar mi respuesta allí: http://stackoverflow.com/questions/4045722/how-to-make-jtextpane-autoscroll-only-when-scroll-bar-is -at-bottom-and-scroll-lo/23654546 # 23654546 –