Question

J'ai créé un menu déroulant sur mon swing jtoolbar. Mais cela ne crée pas de compréhension comme je veux. Je vise que cela fonctionne comme le bouton "Smart Bookmarks" de Firefox.

Il disparaît lorsque l'utilisateur sélectionne un élément de menu: Correct!

Il disparaît lorsque l'utilisateur appuie sur ESC: Correct!

Il disparaît lorsque l'utilisateur clique quelque part dans le cadre principal en dehors du menu: Correct!

Mais il ne disparaît pas lorsque l'utilisateur clique une deuxième fois sur le bouton qui affiche le menu déroulant: incorrect ... :-(

Ma question est de savoir comment puis-je ajouter ce comportement, qu'elle disparaît lorsque le bouton qui montre le menu une deuxième fois.

Voici mon code actuel, de Java 6 sur le 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());
    }
}
Était-ce utile?

La solution

Eh bien, voici une solution potentielle qui n'est pas sans ses inconvénients. Vous seul pouvez décider si cela est acceptable pour votre application. Le problème est que la fermeture contextuelle se produit avant que d'autres événements de manutention de la souris ne soient tirés, alors cliquez sur votre bouton More .. à nouveau provoque une fenêtre contextuelle, réinitialisant ainsi l'état des boutons désélectionnés avant même que le bouton ne soit informé qu'il ait été enfoncé.

La solution de contournement est d'ajouter l'appel suivant dans votre programme principal:

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

Le résultat est que chaque fois qu'un menu contextuel est fermé en raison d'un événement pressé de souris, cet événement de souris sera consommé au moment où le menu est fermé et ne sera transmis à aucun autre composant sous la souris. Si vous pouvez vivre avec une limitation, c'est une solution facile.

Autres conseils

Ce qui se passe, c'est que lorsque vous cliquez sur le menu, il annule le menu contextuel, donc vous désélectionnez le bouton, mais le prochain événement immédiat est de cliquer sur le bouton, et maintenant il est désélectionné afin qu'il affiche à nouveau le menu.

Je n'ai pas encore la solution exacte, mais donnez-moi un peu ...

Je n'utilise pas Firefox, donc je ne sais pas à quoi ressemble le bouton Smart Bookmarks, mais peut-être utiliser un JMenu comme "bouton". Vous pouvez essayer d'utiliser la bordure d'un Jbutton pour le faire ressembler davantage à un bouton.

Eh bien, l'auditeur sur le bouton ne réagit que lorsqu'il est poussé vers le bas, car vous écoutez ItemEvent.SELECTED événements uniquement. Que diriez-vous d'ajouter une autre clause si ItemEvent.DESELECTED Événements ici:

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

Vous pouvez soit stocker une référence au menu quelque part, ou Vous pouvez faire en sorte que le menu lui-même ajoute un autre auditeur au bouton. Cette dernière solution pourrait être plus simple, car vous semblez déjà envoyer une référence de bouton au menu.

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