Comment puis-je faire JScrollPane faites défiler jusqu'à suivre le focus d'entrée?

J'ai un Swing application avec un grand panneau qui est enveloppé dans un JScrollPane. Les utilisateurs se déplacent normalement entre le panneau de sous-composants en surbrillance, alors quand ils onglet à quelque chose hors de vue, je veux la faire défiler le volet de défilement automatique de sorte que le composant avec le focus d'entrée est toujours visible.

J'ai essayé d'utiliser KeyboardFocusManager à écouter pour le focus d'entrée change, et puis l'appel de scrollRectToVisible.

Voici un SSCCE l'affichage de ma stratégie actuelle (il suffit de copier/coller et de les exécuter!):

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 vous exécutez cet exemple, vous remarquerez qu'il ne fonctionne pas très bien. Il ne obtenir le changement de focus de notifications, mais l'appel à la scrollRectToVisible ne semble pas avoir le moindre effet. Dans mon application (qui est trop complexe à voir ici), scrollRectToVisible fonctionne la moitié du temps quand je l'onglet en quelque chose en dehors de la fenêtre d'affichage.

Est-t-il un moyen de résoudre ce problème? Si cela fait une différence, le Swing application est construite sur Netbeans RCP (et la plupart de nos clients exécutent Windows).

OriginalL'auteur gustafc | 2011-11-23