2010-02-02 3 views
4

Je souhaite créer deux ou plusieurs JButton s qui partagent l'état, c.-à-d. Lorsque le bouton de la souris est enfoncé sur JButton, les deux sont affichés comme étant enfoncés (ou "armés") ou, s'ils sont cochés, sont cochée/décochée en même temps, etc.État de partage entre JButtons

Pour l'utilisateur, il doit apparaître comme si les deux boutons étaient le même bouton , apparaissant dans plus d'une place dans la hiérarchie (en réalité swing ne permet pas.)

Je peux arriver à mi-chemin en créant un seul ButtonModel et en assignant le même modèle aux deux boutons. Ceci synchronise leurs états armés/contrôlés/sélectionnés, etc.

Cependant, un effet notable qui est pas partagé entre les boutons de cette façon est le focus - cliquer sur un bouton donne le focus au bouton (indiqué par un rectangle dans le bouton) et le supprime de l'autre bouton. Je voudrais rendre les deux boutons comme s'ils étaient concentrés chaque fois que soit le bouton a vraiment le focus.

Existe-t-il un moyen propre de faire cela?

Idéalement, je voudrais qu'il soit indépendant du look-and-feel choisi.

Modifier: J'ai découvert un autre problème avec le partage d'un ButtonModel. Lorsque l'un des boutons perd le focus, il définit les propriétés armed et pressed du modèle sur false. Cela se produit après en manipulant mousePressed, donc si vous appuyez sur le second bouton lorsque le premier bouton a le focus, il ne passe pas à l'état pressé tant que vous n'appuyez pas dessus une seconde fois.

Répondre

3

Vous avez fait un très bon coup en utilisant le même ButtonModel pour les deux boutons.

Maintenant pour votre problème concernant la mise au point. La réponse est Non. Il n'y a pas de moyen agnostique L&F. Vous devez remplacer BasicButtonUI (ou celui que vous utilisez ButtonUI) et remplacer la logique de mise au point.

+0

Je pense que vous avez raison et il est nécessaire d'étendre ButtonUI, mais il est possible de déléguer à l'interface utilisateur par défaut. Cela fait partie de la technique que j'utilise en ce moment. – finnw

+0

Qu'est ce que c'est L & F? Je l'ai vu dans un autre post. –

+1

@davidblaine L & F = look-and-feel –

1

Je suppose que vous avez déjà du texte, des écouteurs et autres.

En allant à la méthode de peinture de BasicButtonUI, nous pouvons voir qu'il vérifie réellement si le bouton a le focus avant de faire une certaine peinture. Donc, à moins que vous puissiez avoir deux composants focalisés simultanément, la seule façon de le faire que je puisse penser est d'utiliser l'interface utilisateur de l'autre bouton pour peindre.

Les deux boutons doivent être un bouton FocusButton et doivent appeler setButton l'un sur l'autre. Je n'ai pas pris la peine d'ajouter des vérifications nulles, entre autres choses.

public class FocusButton extends JButton { 
    private JButton btn; 

    public FocusButton() { 
     addFocusListener(new FocusListener() { 
      public void focusGained(FocusEvent e) { 
       // Other button seems to repaint when focus is gained anyway 
      } 

      public void focusLost(FocusEvent e) { 
       btn.repaint(); 
      } 
     }); 
    } 

    public void setButton(JButton btn) { 
     this.btn = btn; 
    } 

    public void paint(Graphics g) { 
     if (!btn.hasFocus()) { 
      super.paint(g); 
     } else { 
      btn.paint(g); 
     } 
    } 
} 

EDIT: Cela ne fonctionne ne fonctionne pas trop bien si vos boutons ne sont pas la même taille, et de toute évidence pas du tout s'ils sont censés avoir un texte différent.

+0

Belle idée et a le potentiel d'être la solution la plus simple si elle peut être étendue à 3 boutons ou plus. – finnw

+0

Vous pouvez stocker une liste de boutons au lieu d'un seul, changer de peinture pour utiliser la méthode de celui qui est dans votre liste, et repeindre tout sur le focus perdu. – lins314159

3

Voici ce que je l'ai fait:

  • Extend JButton avec une nouvelle classe SharedFocusButton
  • SharedFocusButtonhasFocus overrides, getModel et paintBorder.
  • Lorsque JButton.paintBorder(Graphics) ou ButtonUI.update(Component, Graphics) est en cours d'exécution, modifiez temporairement le comportement de hasFocus pour qu'il renvoie true si un bouton du groupe a le focus. Modifier temporairement le comportement de getModel pour retourner une procuration ButtonModel (à d'autres moments, il retourne les communes ButtonModel)
  • Le proxy ButtonModel se comporte comme la valeur par défaut, partagée ButtonModel, sauf qu'il refuse de modifier les valeurs des propriétés armed ou pressed à false lors de la gestion d'un événement focusLost. (. Cela ne se produira pas automatiquement parce que chaque bouton a ses propres événements de mise au point de traitement de l'interface utilisateur)
  • Poignée focusGained et focusLost, forçant tous les boutons du groupe pour se redessiner

questions restantes:
Mise au point La traversée devrait probablement être modifiée pour que la touche Tab ne transfère jamais le focus d'un bouton à un autre dans le même groupe.

+0

Je pense que votre solution fonctionnerait mieux que la mienne puisque vous n'êtes pas limité aux boutons de la même taille (difficile à contrôler si l'utilisateur redimensionne votre fenêtre) et à l'apparence. – lins314159