2009-12-14 14 views
8

मैंने अपने स्विंग JToolBar पर एक ड्रॉप-डाउन मेनू बनाया है। लेकिन यह जिस तरह से मैं चाहता हूं व्यवहार नहीं करता है। मैं इसे फ़ायरफ़ॉक्स के "स्मार्ट बुकमार्क्स" बटन की तरह काम करने का लक्ष्य रख रहा हूं।मैं जावा स्विंग टूलबार में "ड्रॉप-डाउन" मेनू कैसे बना सकता हूं?

जब उपयोगकर्ता मेनू आइटम का चयन करता है तो यह गायब हो जाता है: सही!

जब उपयोगकर्ता ईएससी दबाता है तो यह गायब हो जाता है: सही!

यह गायब हो जाता है जब उपयोगकर्ता मेनू के बाहर मुख्य फ्रेम में कहीं भी क्लिक करता है: सही!

लेकिन यह गायब नहीं होता है जब उपयोगकर्ता है कि ड्रॉप-डाउन मेनू से पता चलता बटन पर दूसरी बार क्लिक करता है: गलत ... :-(

मेरा प्रश्न है मैं इस व्यवहार को कैसे जोड़ सकते हैं, कि । जब बटन कि मेनू दूसरी बार चलता पर होने वाले क्लिक

यहाँ मेरे वर्तमान कोड है, पर जावा 6 से मैक यह गायब होता है:

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

इसी का परिणाम है कि जब भी एक पॉपअप मेनू एक माउस दबाया घटना की वजह से बंद कर दिया है, कि माउस घटना हो जाएगा मेनू बंद होने पर उपभोग किया जाता है और माउस के नीचे किसी अन्य घटक पर नहीं भेजा जाएगा। यदि आप सीमा के साथ रह सकते हैं, तो यह एक आसान समाधान है।

+0

एक आकर्षण की तरह काम करता है ... एक प्रश्न: आप इस समाधान के बारे में कैसे जानते थे? क्या यह कहीं दस्तावेज है? –

+1

मैं वास्तव में अपने डीबगर (जेडीके स्रोत संलग्न के साथ) का उपयोग करके यह पता लगाने के लिए था कि घटनाओं को कहां और कब निकाल दिया गया था। मैंने इसे BasicPopupMenuUI में पाया। – BryanD

-1

ठीक है, बटन पर श्रोता केवल जब प्रतिक्रिया करता है इसे धक्का दिया जाता है, क्योंकि आपसुनते हैं केवलघटनाएं। कैसे एक और जोड़ने के बारे में यदि खंड ItemEvent.DESELECTED घटनाओं यहाँ सुनने के लिए:

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

आप या तो कहीं menu के लिए एक संदर्भ संग्रहीत कर सकती है, या आप कर सकते हैं मेनू ही बटन के लिए एक और श्रोता जोड़ें। बाद का समाधान अधिक सरल हो सकता है, क्योंकि आप पहले से ही मेनू के लिए एक बटन संदर्भ भेजना प्रतीत होता है।

+0

Joonas, आप अपने सुझाव की कोशिश की? मैंने कोशिश की है और यह काम नहीं कर रहा है। पॉपअप मेनू बटन पर क्लिक करने पर एक रद्द ईवेंट चलाता है, जो बटन को अचयनित करता है। यह सुनिश्चित करता है कि जब आप उस पर क्लिक करते हैं तो बटन हमेशा चयनित होता है। –

+0

मैंने उपरोक्त कोड का बिल्कुल परीक्षण नहीं किया है, लेकिन मुझे पूरा यकीन है कि इसे जिस तरह से वर्णन किया जाना चाहिए, उसे काम करना चाहिए। हो सकता है कि मुझे कुछ समझ में नहीं आ रहा है, लेकिन popupMenuCanceled() ईवेंट के आधार पर नाजुक लगता है, क्योंकि दस्तावेज़ केवल इतना कहता है कि "पॉपअप मेनू रद्द होने पर यह विधि कॉल की जाती है"। इसका क्या मतलब है? मैं बस बटन के राज्य के लिए एक स्पष्ट श्रोता जोड़ने का सुझाव देता हूं। –

+0

जुनास, समस्या यह है कि आपका सुझाव सिर्फ काम नहीं करता है। इसे आज़माएं और देखें। –

0

मैं फ़ायरफ़ॉक्स का उपयोग नहीं करता इसलिए मुझे नहीं पता कि स्मार्ट बुकमार्क बटन कैसा दिखता है, लेकिन हो सकता है कि एक जेएमएनयू को "बटन" के रूप में उपयोग करें। आप एक बटन की तरह दिखने के लिए जेबटन के सीमा का उपयोग करने का प्रयास कर सकते हैं।

+0

यह चाल करना चाहिए – willcodejavaforfood

+0

यह कोशिश की, यह एक अच्छा परिणाम नहीं है। –

+0

तो आप सुझाव को वोट दें क्योंकि यह आपकी इच्छा के अनुसार नहीं दिखता है। जानना अच्छा है, अगली बार जब मैं आपको "बॉक्स के बाहर" सुझाव देता हूं तो सुझाव देता हूं। मुझे यह काम मिल गया, इसलिए मुझे नहीं पता कि आपको क्या समस्याएं हैं। – camickr

1

बात ये है कि जब आप मेनू बंद क्लिक करें, यह पॉपअप मेनू रद्द करता है, ताकि आप बटन का चयन रद्द, लेकिन अगले तत्काल घटना बटन पर क्लिक किया जाता है, और अब इसके सही का निशान हटाने तो यह मेनू फिर से पता चलता है।

मैं अभी तक सटीक समाधान की जरूरत नहीं है, लेकिन मुझे एक छोटा सा दे ...

संबंधित मुद्दे