2009-10-09 5 views
4

J'ai un problème avec le comportement JTextField.requestFocus() qui semble être différent sous Mac OS X.Mac problèmes L & F: comportement des JTextField.requestFocus Diffère()

Voici ma situation: j'ai un dialogue avec un JList et un JTextField. L'utilisateur est censé écrire une expression booléenne dans le champ de texte, et la liste contient les noms de toutes les variables qui pourraient être entrées dans l'expression. Étant donné que l'utilisateur doit continuer à entrer l'expression après avoir cliqué sur une variable de la liste, le programme appelle utilement JTextField.requestFocus(). De cette façon, vous pouvez, par exemple, cliquer sur "pvalue" dans la liste, puis taper "< 0.05" sans avoir à cliquer sur le champ de texte entre les deux. Tout fonctionne très bien sur ma machine de développement (Linux), mais j'ai reçu un rapport de bogue d'un utilisateur Mac qui en cliquant sur la liste sélectionne tout le texte dans le champ de texte, ce qui facilite l'écrasement accidentel de ce qui a été saisi auparavant .

Je pensais que c'était un problème avec le look-and-feel de Mac, après quelques recherches, il semble qu'il existe en effet une propriété "Quaqua.TextComponent.autoSelect" pour le look-and-feel mac qui semble être lié à ce problème: http://www.randelshofer.ch/quaqua/guide/jtextcomponent.html

Ma question générale est:

  • Pouvez-vous suggérer une solution à ce problème?

Dans le cas qui est trop large, une réponse à ces questions secondaires serait déjà une grande aide:

  • Une solution possible pourrait être de changer la propriété « Quaqua.TextComponent.autoSelect ». Comment je fais ça?
  • Je ne suis même pas sûr de ce qu'est "Quaqua". Il semble que ce soit un aspect personnalisé. Quelle est l'apparence par défaut de Mac OS X? A-t-il une propriété similaire à Quaqua.TextComponent.autoSelect?
  • Existe-t-il une possibilité de modifier l'apparence d'une seule instance de composant? Si c'est le cas, comment?
  • Est-ce qu'il est possible de configurer l'apparence du Mac sur ma machine de développement Linux pour que je puisse réellement confirmer ce bug (tout ce qui précède est vraiment basé sur des intuitions et des soupçons)? Si c'est le cas, comment?

Répondre

2

Pour modifier le comportement par défaut, vous pouvez définir la propriété système false avant d'initialiser les composants de l'interface utilisateur: System.setProperty("Quaqua.TextComponent.autoSelect", "false"); Pour modifier un seul composant, vous pouvez utiliser JTextField#putClientProperty("Quaqua.TextComponent.autoSelect", Boolean.FALSE);.

Vous pouvez trouver d'autres propriétés spécifiques L & F Mac OS ici:

Quaqua Look & Feel - User Guide

+0

C'est utile, mais il semble que Quaqua est un look and feel, pas nécessairement ce que mes utilisateurs utilisent. – amarillion

+0

Oui, il s'agit d'une extension de la version par défaut de MacOS L & F, qui modifie malheureusement également le comportement des composants (par exemple, en sélectionnant le contenu de TextFields focus) et non seulement modifie le L & F réel. Je me rends compte qu'il est difficile pour vous de faire face à tout cela dans votre application, mais vous pouvez au moins suggérer aux utilisateurs de Quaqua de définir la propriété système en externe (-DQuaqua.TextComponent.autoSelect = false) lors du démarrage de l'application. – jarnbjo

1

Je remarquai en regardant à travers les JavaDocs que requestFocus() « est découragée parce que son comportement est dépendant de la plateforme. » Vous devriez utiliser requestFocusInWindow() à la place et voir si le même problème se produit avec elle. RequestFocusInWindow fait partie du Focus subsystem, introduit en Java 1.4.

Sur une note côté, la valeur par défaut Recherchez Apple et Feel a au moins une propriété dans l'espace de noms apple.laf: apple.laf.useScreenMenuBar

Edit: According to Sun, le look Macintosh et la sensation est disponible uniquement sur Mac.

+0

Bon conseil, je vais essayer requestFocusInWindow. Aussi, c'est dommage que je ne puisse pas tester le Mac L & F, mais il est bon de le savoir au moins. – amarillion

+0

Malheureusement, il s'avère que requestFocusInWindow() a le même problème. – amarillion

1

Si l'utilisation de requestFocusInWindow() est en effet encouragée par rapport à requestFocus(), elle produit toujours le même comportement problématique sur les Mac (par exemple, mise en surbrillance du champ de texte intégral).

Une solution que je suis arrivé au travail était de définir explicitement la position du curseur après avoir demandé mise au point:

JTextField.requestFocusInWindow(); 
JTextField.setCaretPosition(JTextField.getDocument().getLength() - 1); 

Notez le « -1 » est nécessaire, sinon il continuera à mettre en évidence le champ.

Je suis curieux de savoir si cette solution est indépendante de la plate-forme. Est-ce que cela bousille le comportement Linux ou Windows souhaité?

+0

Merci d'avoir vérifié le comportement de requestFocusInWindow(), car je n'ai pas de Mac. Déplacer la position du curseur n'est pas idéal, mais peut-être est-il possible de déplacer le curseur deux fois pour le ramener à l'endroit où il devrait être? – amarillion

2

Une solution de contournement peut être (et je n'ai pas testé cela) pour rendre le JList insère les noms de variables non mis au point. De cette façon, l'accent restera dans le champ de texte lorsque vous cliquez sur un élément de la liste. Je recommande d'utiliser setRequestEnabled(false) sur le JList, de sorte qu'ils sont encore focalisables si vous leur attachez un onglet, mais en cliquant dessus avec la souris ne les mettra pas au point.

1

Désolé pour ajouter à une vieille question, mais je suis tombé sur ce problème et a utilisé le code suivant, qui semble un peu plus complet que l'exemple précédent:

// JTextField linkedText 
final int 
    startBefore = linkedText.getSelectionStart(), 
    endBefore = linkedText.getSelectionEnd(); 
linkedText.requestFocus(); // this was the original code line! 
SwingUtilities.invokeLater(new Runnable() 
{ 
    public void run() 
    { 
    linkedText.setSelectionStart(startBefore); 
    linkedText.setSelectionEnd(endBefore); 
    } 
}); 

Cela semble protéger le curseur position ou sélection. (Remarque: Ce code doit déjà être exécuté dans le fil d'expédition d'événement, mais vous devez invokeLater de toute façon ou cela ne fonctionne pas.)

J'ai une fonction 'is Mac', donc j'ai fait ceci dans un test pour cela, mais cela ne fait probablement aucun mal de le faire sur toutes les plateformes.

3

Semble que c'est un bug de Mac OS. JTextFields sélectionne son contenu lorsqu'il acquiert le focus par le biais d'un cycle de tabulation du clavier. Si le point d'insertion est au milieu du texte, le point d'insertion restera et le texte entier ne sera pas sélectionné.

Pour contourner ce problème, vous pouvez modifier ce comportement avec ce qui suit, il fonctionne très bien pour moi:

textfield.setCaret(new DefaultCaret()).

Plus de détails vous pouvez consulter this et this.

+0

wow cet appel simple l'a réparé! J'espérais qu'il y aurait une solution plus simple que de repositionner le curseur et c'était tout. Je vous remercie. –

0

Mac sélectionne le contenu du champ de texte lorsque le champ est activé. Vous pouvez restaurer l'état du champ de texte si vous écoutez l'événement de changement de focus.

// JTextField linkedText 
// Cache the state of the JTextField prior to requesting focus 
final int 
    startBefore = linkedText.getSelectionStart(), 
    endBefore = linkedText.getSelectionEnd(); 
linkedText.requestFocus(); // this was the original code line! 

// Use a focus listener to listen for the focus change and then 
// reset the selected text to protect the cursor position 
linkedText.addFocusListener (new FocusListener() 
{ 
    public void focusGained(FocusEvent event) { 
     linkedText.setSelectionStart(startBefore); 
     linkedText.setSelectionEnd(endBefore); 
    } 

    public void focusLost(FocusEvent event) { 
     // do nothing 
    } 
}); 
0

Merci de partager vos idées. J'ai eu le même problème sur mon application Java où sur mon système Windows il n'y avait pas de problème, mais sur mon Mac OS X Yosemite je ne pouvais pas changer l'entrée. L'accent ne resterait pas sur le JTextField. Grâce à ce fil j'ai pu résoudre mon problème.

Si vous modifiez l'aspect et la convivialité des boutons et des zones de saisie, vous maintenez le focus et vous pouvez taper à nouveau.La réinitialisation de l'image reste dans l'apparence standard de Mac OS.

Ceci est mon code que j'utilise dans ma méthode principale java. Si vous voulez résoudre le problème après le code try-catch dans votre méthode principale.

public class Venster extends JFrame { 

    public static void main(String[] args) { 

     //Change L&F for mac 
     //Mac JTextField Bug Fix 
     try { 
      // Set cross-platform Java L&F (also called "Metal") 
      UIManager.setLookAndFeel(
        UIManager.getCrossPlatformLookAndFeelClassName()); 
     } catch (UnsupportedLookAndFeelException e) { 
      System.out.println("L&F not supported" + e.getMessage()); 

     } catch (ClassNotFoundException e) { 
      System.out.println("Fout: " + e.getMessage()); 
     } catch (InstantiationException e) { 
      System.out.println("Fout: " + e.getMessage()); 
     } catch (IllegalAccessException e) { 
      System.out.println("Fout: " + e.getMessage()); 
     } 

     //The app 
     JFrame frame = new JFrame(); 
     frame.setSize(1000, 520); 
     frame.setResizable(false); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setTitle("10 More Bullets by Frank Peters"); 
     frame.setContentPane(new SpeelVeld()); 
     frame.setVisible(true); 
     frame.setLocationRelativeTo(null); //start app in center 
    } 
} 

Soure: http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html

Questions connexes