Tengo una aplicación Swing con un panel grande que está envuelto en un JScrollPane
. Los usuarios normalmente se mueven entre los subcomponentes del panel mediante pestañas, de modo que cuando seleccionan un tabulador para ver algo, quiero que el panel de desplazamiento se desplace automáticamente para que el componente con enfoque de entrada esté siempre visible.¿Cómo hago que JScrollPane scroll siga el enfoque de entrada?
He intentado usar KeyboardFocusManager
para escuchar cambios en el foco de entrada, y luego llamar al scrollRectToVisible
.
He aquí un SSCCE mostrar mi estrategia actual (sólo tienes que copiar/pegar y correr!):
import java.awt.KeyboardFocusManager;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
public class FollowFocus {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
final int ROWS = 100;
final JPanel content = new JPanel();
content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS));
content.add(new JLabel(
"Thanks for helping out. Use tab to move around."));
for (int i = 0; i < ROWS; i++) {
JTextField field = new JTextField("" + i);
field.setName("field#" + i);
content.add(field);
}
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.addPropertyChangeListener("focusOwner",
new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (!(evt.getNewValue() instanceof JComponent)) {
return;
}
JComponent focused = (JComponent) evt.getNewValue();
if (content.isAncestorOf(focused)) {
System.out.println("Scrolling to " + focused.getName());
focused.scrollRectToVisible(focused.getBounds());
}
}
});
JFrame window = new JFrame("Follow focus");
window.setContentPane(new JScrollPane(content));
window.setSize(200, 200);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
}
});
}
}
Si ejecuta este ejemplo, se dará cuenta de que no funciona muy bien. Recibe las notificaciones de cambio de foco, pero la llamada a scrollRectToVisible
no parece tener ningún efecto. En mi aplicación (que es demasiado compleja para mostrar aquí), scrollRectToVisible
funciona la mitad del tiempo cuando tabulo en algo fuera de la ventana gráfica.
¿Existe alguna manera establecida de resolver este problema? Si hace alguna diferencia, la aplicación Swing se basa en Netbeans RCP (y la mayoría de nuestros clientes ejecutan Windows).
Gracias por la explicación. –
Sí, gracias por la explicación. La solución propuesta no funcionaba en mi aplicación (aunque funcionaba como un encanto en el ejemplo anterior), pero después de un poco de experimentación, encontré que lo siguiente funcionaba: '((JComponent) focused.getParent()). ScrollRectToVisible (focused.getBounds()) 'Ahora, nadie respira o el seguidor de enfoque se rompe ...;) – gustafc