Pregunta

Ahora, tengo un jmenu, y algunos jmenuitems en él.Quiero que mi programa realice alguna acción cuando el estado de Jmenu y Jmenuitem se cambie a "seleccionado".No uso el mouseOver de Mouseelitener, porque quiero que el usuario pueda navegar en el menú con teclados también.Ahora, escribí este oyente:

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

Cuando agrego este oyente a Jmenu, funciona correctamente, pero cuando lo agrego a Jmenuitem, nada sucede ... Cuando eliminé la instrucción si el oyente reaccione ambos, cuando el menú está seleccionado y deseleccionado, funciona bien para JMENU.así como para jmenuitem.Entonces, como veo, Jmenuitem no puede "pasar" la prueba () isselected (), pero ¿qué puede ser un problema?: S

¿Fue útil?

Solución

Sin ofensa destinada en ninguna dirección, esta es solo una de esas preguntas con un historial

  • Requisito inicial: hacer algo cuando un mouse está sobre jmenuitem
  • Darling de todos: Mouselistener
  • Sugerencia de desviación inicial (Kudos a @mkorbel!): Changelistener en el botón de botón, revisando la propiedad Rollover

  • Requisito refinado: Dosalgo cuando Jmenuitem acaba de resaltar, tanto del teclado como por el mouse sobre.

  • Refinado Darling: ChangElistener en el botón de botón, propiedad no especificada
  • Desviación refinada: ActionListener

  • Requisito actual: Dosalgo cuando se modificó la propiedad JMENU o JMENUITEM "seleccionada".

  • Darling actual: no se puede hacer con un oyente, anular ...
  • desviaciones actuales: acción, menulistener ...

    El correcto y completo (en retrospectiva, sin embargo, como el teclado aún no se mencionó) la respuesta ya estaba disponible en la primera ronda: algunos oyentes semánticos que es "lo suficientemente bajo" para capturar los cambios estatales (los candidatos son rollover , armado, seleccionado, presionado en el nivel de botón de botón) que hacen que los menuitems cambien su estado resaltado . Desafortunadamente, la relación exacta no es bien conocida (para mí, al menos), indocumentada (lea: Lazy Younch No pudo encontrar nada en una mirada rápida) e incluso confundir (de nuevo, para mí), ya que la rollover es falsa siempre (?) para Menuitems

    La reacción del experimentalista es .. Intente: A continuación, se encuentra un fragmento de código que escucha y registra los cambios en el estado en algún árbol de menú (simplemente lanzan a un barbar arbitrario y mueve el mouse y navegue por el teclado).

    y el ganador es: - Use un ChangElistener y compruebe si la fuente está seleccionada o armada.

        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());
                    }
                }
            }
        };
    

    Funciona para el teclado y el mouse, ambos JMENU y JMENUITEM

    //----------- 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;
    }
    

Otros consejos

Este es el comportamiento polimorfo esperado.El método isSelected() de JMenuItem se hereda del AbstractButton, mientras que el mismo método en Jmenu es anuladopara que "devuelva verdadero si el menú está actualmente seleccionado (resaltado)".

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top