Pregunta

He creado un menú desplegable en mi swing jtoolbar. Pero no crea comportarse como quiero. Estoy apuntando a que funcione como el botón "marcadores inteligentes" de Firefox.

Desaparece cuando el usuario selecciona un elemento de menú: ¡correcto!

Desaparece cuando el usuario presiona ESC: ¡correcto!

Desaparece cuando el usuario hace clic en el marco principal fuera del menú: ¡Correcto!

Pero no desaparece cuando el usuario hace clic por segunda vez en el botón que muestra el menú desplegable: Incorrecto ... :-(

Mi pregunta es cómo puedo agregar este comportamiento, que desaparece cuando los clics en el botón que muestra el menú por segunda vez.

Aquí está mi código actual, de Java 6 en la Mac:

import javax.swing.*;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;

public class ScratchSpace {

    public static void main(String[] arguments) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new JFrame("Toolbar with Popup Menu demo");

                final JToolBar toolBar = new JToolBar();
                toolBar.add(createMoreButton());

                final JPanel panel = new JPanel(new BorderLayout());
                panel.add(toolBar, BorderLayout.NORTH);
                panel.setPreferredSize(new Dimension(600, 400));
                frame.getContentPane().add(panel);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    private static AbstractButton createMoreButton() {
        final JToggleButton moreButton = new JToggleButton("More...");
        moreButton.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                if (e.getStateChange() == ItemEvent.SELECTED) {
                    createAndShowMenu((JComponent) e.getSource(), moreButton);
                }
            }
        });
        moreButton.setFocusable(false);
        moreButton.setHorizontalTextPosition(SwingConstants.LEADING);
        return moreButton;
    }

    private static void createAndShowMenu(final JComponent component, final AbstractButton moreButton) {
        JPopupMenu menu = new JPopupMenu();
        menu.add(new JMenuItem("Black"));
        menu.add(new JMenuItem("Red"));

        menu.addPopupMenuListener(new PopupMenuListener() {
            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
            }

            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
                moreButton.setSelected(false);
            }

            public void popupMenuCanceled(PopupMenuEvent e) {
                moreButton.setSelected(false);
            }
        });

        menu.show(component, 0, component.getHeight());
    }
}
¿Fue útil?

Solución

Bueno, aquí hay una solución potencial que no está exenta de sus inconvenientes. Solo usted puede decidir si esto es aceptable para su solicitud. El problema es que el cierre emergente ocurre antes de que otros eventos de manejo del mouse se disparen, por lo que hacer clic en su más.

La solución fácil es agregar la siguiente llamada dentro de su programa principal:

UIManager.put("PopupMenu.consumeEventOnClose", Boolean.TRUE);

El resultado de esto es que cada vez que se cierre un menú emergente debido a un evento prensado del mouse, ese evento del mouse se consumirá en el momento en que el menú está cerrado y no se transmitirá a ningún otro componente debajo del mouse. Si puede vivir con limitación, esta es una solución fácil.

Otros consejos

Lo que está sucediendo es que cuando hace clic en el menú, cancela el menú emergente, por lo que deselecciona el botón, pero el siguiente evento inmediato es hacer clic en el botón y ahora está deseleccionado, por lo que muestra el menú nuevamente.

Todavía no tengo la solución exacta, pero dame un poco ...

No uso Firefox, así que no sé cómo se ve el botón Smart Bookmarks, pero tal vez use un JMenu como "botón". Puede intentar usar el borde de un JButton para que se vea más como un botón.

Bueno, el oyente en el botón reacciona solo cuando se presiona hacia abajo, porque escuchas ItemEvent.SELECTED solo eventos. ¿Qué tal agregar otra cláusula if para escuchar ItemEvent.DESELECTED Eventos aquí:

    moreButton.addItemListener(new ItemListener() {
        public void itemStateChanged(ItemEvent e) {
            if (e.getStateChange() == ItemEvent.SELECTED) {
                createAndShowMenu((JComponent) e.getSource(), moreButton);
            }
        }
    });

Podrías almacenar una referencia al menu en algún lugar, o Puede hacer que el menú en sí agregue otro oyente al botón. La última solución podría ser más sencilla, ya que ya parece enviar una referencia de botón al menú.

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