Как создать раскрывающееся меню на панели инструментов Java Swing?

Я создал раскрывающееся меню на моем Swing JToolBar. Но это не создает поведения, которое я хочу. Я стремлюсь к тому, чтобы он работал как кнопка "умные закладки" Firefox.

он исчезает, когда пользователь выбирает пункт меню: правильно!

он исчезает, когда пользователь нажимает ESC: правильно!

он исчезает, когда пользователь щелкает где-то в главном фрейме вне меню: правильно!

, но он не исчезает, когда пользователь щелкает второй раз на кнопке, которая показывает выпадающее меню: неверно... :-(

мой вопрос: как я могу добавить это поведение, что оно исчезает, когда нажимает на кнопку, которая показывает меню во второй раз.

вот мой текущий код, из Java 6 на 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());
    }
}

4 ответов


Ну, вот потенциальное решение, которое не лишено недостатков. Только вы можете решить, является ли это приемлемым для вашего приложения. Проблема в том, что всплывающее закрытие происходит до того, как другие события обработки мыши будут запущены, поэтому нажмите на Ваш больше.. кнопка снова заставляет всплывающее окно скрываться, таким образом, сбрасывая состояние кнопок, чтобы отменить выбор, прежде чем кнопка даже будет сказано, что она была нажата.

простой обходной путь-добавить следующий вызов в основной программа:

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

результатом этого является то, что всякий раз, когда всплывающее меню закрывается из-за события, нажатого мышью, это событие мыши будет потребляться во время закрытия меню и не будет передано другим компонентам под мышью. Если вы можете жить с ограничениями, это простое решение.


Что происходит, когда вы щелкаете по меню, оно отменяет всплывающее меню, поэтому вы отменяете выбор кнопки, но следующее немедленное событие нажимает кнопку, и теперь его отменяют, чтобы он снова показывал меню.

У меня еще нет точного решения, но дайте мне немного ...


Я не использую Firefox, поэтому я не знаю, как выглядит кнопка смарт-закладок, но, возможно, используйте JMenu в качестве "кнопки". Вы можете попробовать использовать границу JButton, чтобы сделать ее более похожей на кнопку.


ну, слушатель на кнопке реагирует только тогда, когда он нажат, потому что вы слушаете