Question

Maintenant, j'ai un JMenu, et quelques jméiuites. Je veux que mon programme effectue une action lorsque l'état de JMenu et JMenuItem est changé en "sélectionné". Je n'utilise pas la souris de MouseLitener, car je veux que l'utilisateur puisse également naviguer dans le menu à l'aide des claviers. Maintenant, j'ai écrit cet auditeur:

class MenuItemListener implements ChangeListener {
    @Override
    public void stateChanged(ChangeEvent arg0) {
        JMenuItem item = (JMenuItem) arg0.getSource();
        if(item.isSelected())
            System.out.println(item.getText()+" pressed!");
    }
}

Lorsque j'ajoute cet auditeur à JMenu, cela fonctionne correctement, mais lorsque je l'ajoute à JMenuItem, rien ne se passe ... lorsque je supprime si l'instruction pour que l'écouteur réagisse les deux, lorsque le menu est sélectionné et désexé, je fonctionne bien pour JMenu ainsi que bien que ce Pour JMenuItem. Donc, comme je le vois, JMenuItem ne peut pas "passer" isselected () test ... mais quel peut être un problème? : S

Était-ce utile?

La solution

Aucune infraction prévue dans aucune direction, ce n'est qu'une de ces questions avec une histoire

  • Exigence initiale: faire quelque chose lorsqu'une souris est sur JMenuitem
  • Initial Everybody's Darling: Mouselistener
  • Suggestion déviante initiale (bravo à @mkorbel!): ChangeListener sur le boutonmode, vérifiant la propriété Rollover

  • Exigence raffinée: Dosomething Lorsque JMenuItem vient de mettre en évidence, à la fois par le clavier et la souris.

  • Darling raffiné: ChangeListener sur le boutonmode, propriété non spécifiée
  • Déviation raffinée: ActionListener

  • Exigence actuelle: Dosomething Lorsque la propriété JMENU ou JMENUiTeM "sélectionnée" a changé.

  • Current Darling: Impossible de finir avec un auditeur, de remplacer ...
  • Écarts actuels: action, Menulistener ...

La réponse correcte et complète (avec le recul, car le clavier n'a pas encore été mentionné) était déjà disponible au premier tour: un auditeur sémantique qui est "assez de bas niveau" pour capturer les changements d'état (les candidats sont le roulement, armé, sélectionné, appuyé sur le niveau de bouton-bouton) qui fait changer les menuites Souligné Etat. Malheureusement, la relation exacte n'est pas bien connue (pour moi, au moins), sans papiers (lire: paresseux moi n'a rien trouvé sur un coup d'œil rapide) et même déroutant (encore une fois, pour moi) car le roulement est faux toujours (?) pour les menuites

La réaction de l'expérimentaliste est de .. Essayez: Ci-dessous est un extrait de code qui écoute et enregistre l'état change sur une arborescence de menu (jetez simplement dans un menubar arbitraire et déplacez la souris et naviguez par clavier).

Et le gagnant est: - Utilisez un ChangeListener et vérifiez si la source est sélectionnée ou armée.

    ChangeListener ch = new ChangeListener() {

        @Override
        public void stateChanged(ChangeEvent e) {
            if (e.getSource() instanceof JMenuItem) {
                JMenuItem item = (JMenuItem) e.getSource();
                if (item.isSelected() || item.isArmed()) {
                    System.out.println("Highlighted: " + item.getActionCommand());
                }
            }
        }
    };

Fonctionne à la fois pour le clavier et la souris, JMenu et JMenuem

//----------- code snippet to track property changes in menuItem/buttonModel

    // test menu
    JMenu menu = new JMenu("Sample menu");
    menu.setMnemonic('s');
    installListeners(menu);

    // first menuitem
    JMenuItem other = menu.add("content1");
    installListeners(other);
    // second menuitem
    other = menu.add("again + ");
    installListeners(other);

    // sub
    JMenu sub = new JMenu("subMenu");
    installListeners(sub);
    menu.add(sub);

    // menus in sub
    other = sub.add("first in sub");
    installListeners(other);
    other = sub.add("second in sub");
    installListeners(other);

    getJMenuBar().add(menu);

private void installListeners(JMenuItem menu) {
    menu.getModel().addChangeListener(getChangeListener());
    menu.addChangeListener(getChangeListener());
}

private ChangeListener getChangeListener() {
    ChangeListener ch = new ChangeListener() {

        @Override
        public void stateChanged(ChangeEvent e) {
            if (e.getSource() instanceof ButtonModel) {
                ButtonModel model = (ButtonModel) e.getSource();
                System.out.println("from model: " + createStateText(model));
            } else if (e.getSource() instanceof JMenuItem) {
                JMenuItem item = (JMenuItem) e.getSource();
                System.out.println("  from item: " + createStateText(item));
            }
        }

        private String createStateText(ButtonModel model) {
            String text = model.getActionCommand() + " armed: " + model.isArmed();
            text += " selected: " + model.isSelected();
            text += " rollover " + model.isRollover();
            text += " pressed: " + model.isPressed();
            return text;
        }

        private String createStateText(JMenuItem model) {
            String text = model.getActionCommand() + " armed: " + model.isArmed();
            text += " selected: " + model.isSelected();
            // not supported on JMenuItem nor on AbstractButton
           // text += " rollover " + model.isRollover();
           // text += " pressed: " + model.isPressed();
            return text;
        }
    };
    return ch;
}

Autres conseils

Il s'agit du comportement polymorphe attendu. La isSelected() méthode de JMenuItem est hérité de AbstractButton, tandis que la même méthode dans Jmenu est remplacé afin qu'il "renvoie True si le menu est actuellement sélectionné (surligné)".

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top