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
Vous devez vous connecter pour publier un commentaire.
Mon commentaire à l'autre de répondre:
... sauf quand le composant lui-même traite - comme component swing jtextfield: il est mis en œuvre pour faire défiler horizontalement pour faire le signe visible. La solution est d'appeler la méthode sur le terrain du parent.
Modifier
juste pour plus de clarté, le remplacement de la ligne est
Oui, merci pour l'explication. Votre proposition de corrigé n'a pas de travail dans mon application (si elle a fonctionné comme un charme dans l'exemple ci-dessus), mais après un peu d'expérimentation, j'ai trouvé:
((JComponent) focused.getParent()).scrollRectToVisible(focused.getBounds())
Maintenant, personne ne respirer ou de la cible adepte des pauses... 😉OriginalL'auteur kleopatra
vous avez à prendre
Rectangle
deJPanel
etJViewPort
trop, puis de comparer, par exempleavis (contre bas droit de vote) pour la finale et agréable de sortie nécessaire à certains travaux pour des postes dans le
JViewPort
avoir à se replier un peu sur b) - la référence à un contenu n'est pas nécessaire pour le défilement, il est nécessaire de vérifier si le concentré est dans le contenu de la hiérarchie enfant
OriginalL'auteur mKorbel
Un problème majeur dans votre code est:
Vous appelez scrollRectToVisible sur le composant lui-même! Sans doute une faute de frappe.
Faites votre JScrollPane une dernière variable et appel
Je ne le savais pas. La modification que j'ai proposé fonctionne très bien mais je n'ai pas idée de pourquoi ça ne fonctionne pas comme il est.
voir ma réponse au pourquoi (avez remarquez le type de composant seulement après la publication du commentaire) Néanmoins, ne pas message de la fenêtre d'affichage directement pour le code de la santé mentale
OriginalL'auteur Ashwinee K Jha
Ici jtextbox est le composant que vous voulez mettre l'accent, et jscrollpane est votre composant scrollpane:
OriginalL'auteur user2822578