كيف يمكنني إنشاء قائمة "المنسدلة" في شريط أدوات جافا سوينغ؟

StackOverflow https://stackoverflow.com/questions/1900293

سؤال

لقد قمت بإنشاء قائمة منسدلة على سوينغ 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());
    }
}
هل كانت مفيدة؟

المحلول

حسنا، إليك حل محتمل ليس بدون عيوبه. فقط يمكنك أن تقرر ما إذا كان هذا مقبول للتطبيق الخاص بك. المشكلة هي أن الإغلاق المنبثقة يحدث قبل إطلاق الأحداث الأخرى مناولة الماوس، لذلك النقر فوق الزرك الخاص بك.

الحل السهل هو إضافة المكالمة التالية في البرنامج الرئيسي الخاص بك:

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

نتيجة ذلك هي أنه كلما تم إغلاق قائمة منبثقة بسبب حدث مضغوط من الماوس، سيتم استهلاك حدث الماوس هذا في الوقت الذي يتم فيه إغلاق القائمة ولن يتم تمريره إلى أي مكونات أخرى تحت الماوس. إذا كنت تستطيع العيش مع القيد، فهذا هو الحل السهل.

نصائح أخرى

ما يحدث هو أنه عند النقر فوق القائمة، يقوم بإلغاء قائمة المنبثقة، بحيث تقوم بإلغاء تحديد الزر، ولكن الحدث الفوري التالي هو النقر فوق الزر، والآن يتم إلغاء تحديده بحيث يظهر القائمة مرة أخرى.

ليس لدي الحل الدقيق حتى الآن، ولكن أعطني قليلا ...

لا أستخدم Firefox، لذلك لا أعرف ما يبدو زر الإشارات الذكية، ولكن ربما استخدم JMenu ك "زر". يمكنك محاولة استخدام حدود JButton لجعلها تبدو أكثر مثل زر.

حسنا، يتفاعل المستمع على الزر فقط عندما يتم دفعه، لأنك تستمع ItemEvent.SELECTED الأحداث فقط. ماذا عن إضافة آخر إذا جملة للاستماع ItemEvent.DESELECTED الأحداث هنا:

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

يمكنك إما تخزين مرجع إلى menu مكان ما، أو يمكنك جعل القائمة نفسها إضافة مستمع آخر إلى الزر. يمكن أن يكون الحل الأخير أكثر وضوحا، لأنك يبدو بالفعل لإرسال إشارة زر إلى القائمة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top