2010-10-14 10 views
8

मैंने कुछ बार key bindings पर निश्चित ट्यूटोरियल पढ़ा है, लेकिन मेरी मस्तिष्क कैश जटिल प्रक्रियाओं को पकड़ने के लिए पर्याप्त नहीं लगती है।जावा प्रेषण कुंजी कैसे करता है?

मैं एक महत्वपूर्ण बंधन समस्या (निकला मैं गलत JComponent.WHEN_* हालत उपयोग कर रहा था) डिबगिंग गया था, और मैं पैकेज निजी javax.swing.KeyboardManager एक (दुर्भाग्य से) गुमनाम जावा इंजीनियर द्वारा के लिए एक संक्षिप्त और प्रफुल्लित जावाडोक पर ठोकर खाई।

मेरा प्रश्न यह है: KeyEventDispatcher को छोड़कर जो बहुत शुरुआत में चेक किया गया है, विवरण मिस और/या कुछ गलती करता है?

KeyboardManager वर्ग WHEN_IN_FOCUSED_WINDOW शैली कार्यों के लिए मदद प्रेषण कुंजीपटल कार्यों के लिए इस्तेमाल किया जाता है। अन्य स्थितियों के साथ क्रियाएं सीधे JComponent में संभाली गई हैं।

यहाँ symantics कैसे कुंजीपटल भेजने कम से कम [वैसा] काम करना चाहिए के रूप में मैं इसे समझ की [वैसा] का वर्णन दिया गया।

KeyEvents केंद्रित घटक पर प्रेषित किए जाते हैं। फोकस प्रबंधक इस ईवेंट को संसाधित करने पर पहली क्रैक प्राप्त करता है। यदि फोकस प्रबंधक नहीं चाहता है, तो JComponent super.processKeyEvent() को कॉल करता है, यह श्रोताओं को ईवेंट को संसाधित करने का मौका देता है।

यदि श्रोताओं में से कोई भी घटना का उपभोग नहीं करता है तो कुंजीबंडिंग शॉट प्राप्त करती है। यह वह जगह है जहां चीजें से शुरू होती हैं दिलचस्प हो जाती है। सबसे पहले, KeyStokes [sic] WHEN_FOCUSED स्थिति के साथ परिभाषित एक मौका मिलता है। यदि में से कोई भी ईवेंट नहीं चाहता है, तो घटक चलता है हालांकि यह [एसआईसी] माता-पिता WHEN_ANCESTOR_OF_FOCUSED_COMPONENT प्रकार के कार्यों की तलाश में है।

यदि कोई इसे अभी तक नहीं ले गया है, तो यह यहां हवाओं को चलाता है। इसके बाद हम घटक WHEN_IN_FOCUSED_WINDOW ईवेंट और आग के लिए पंजीकृत घटक देखें। ध्यान दें कि यदि उनमें से कोई भी नहीं मिला है तो हम ईवेंट को मेन्यूबार पर पास करते हैं और उन्हें पर क्रैक करने दें। वे अलग-अलग संभाले जाते हैं।

आखिरकार, हम जांचते हैं कि हम एक आंतरिक फ्रेम देख रहे हैं या नहीं। यदि हम हैं और कोई ईवेंट चाहता था तो हम को इंटरनलफ्रेम के निर्माता को ले जाएं और देखें यदि कोई ईवेंट चाहता है (और और इसी तरह)।


(अपडेट) यदि आप कभी भी कुंजी बाइंडिंग गाइड में इस बोल्ड चेतावनी के बारे में सोचा गया है:

क्योंकि घटकों की खोज का आदेश अप्रत्याशित है, बचने नकल WHEN_IN_FOCUSED_WINDOW बाइंडिंग!,

 Object tmp = keyMap.get(ks); 
    if (tmp == null) { 
     // don't do anything 
    } else if (tmp instanceof JComponent) { 
      ... 
    } else if (tmp instanceof Vector) { //more than one comp registered for this 
     Vector v = (Vector)tmp; 
      // There is no well defined order for WHEN_IN_FOCUSED_WINDOW 
      // bindings, but we give precedence to those bindings just 
      // added. This is done so that JMenus WHEN_IN_FOCUSED_WINDOW 
      // bindings are accessed before those of the JRootPane (they 
      // both have a WHEN_IN_FOCUSED_WINDOW binding for enter). 
      for (int counter = v.size() - 1; counter >= 0; counter--) { 
     JComponent c = (JComponent)v.elementAt(counter); 
     //System.out.println("Trying collision: " + c + " vector = "+ v.size()); 
     if (c.isShowing() && c.isEnabled()) { // don't want to give these out 
      fireBinding(c, ks, e, pressed); 
     if (e.isConsumed()) 
      return true; 
     } 
    } 

तो खोज के क्रम में वास्तव में उम्मीद के मुताबिक, लेकिन स्पष्ट रूप से इस विशेष कार्यान्वयन पर निर्भर है तो यह बेहतर है नहीं पर भरोसा करने की:

यह KeyboardManager#fireKeyboardAction में इस सेगमेंट की वजह से इसको बिलकुल भी नहीं। इसे अप्रत्याशित रखें।

(जावाडोक और कोड WinXP पर jdk1.6.0_b105 से है।)

+0

यह KeyEvent हैंडलिंग पर एक अच्छा विश्लेषण है ... लेकिन मुझे नहीं पता कि यह वास्तव में एक प्रश्न है जो उत्तरदायी है। – BoffinbraiN

+0

@BoffinbraiN: मुझे उम्मीद थी कुछ दर्जन स्विंग बैज के साथ किसी का कहना है कि कुछ की तरह "मेरी जानकारी के अनुसार यह सही है" :) –

+1

हाँ, वह निश्चित रूप से बेहतर हो गया होता! लेकिन मुझे लगता है कि इस गहरे कुछ के लिए, यह वास्तव में कार्यान्वयन-विशिष्ट है, और आपने इस कार्यान्वयन की जांच अब तक की सबसे मेहनती प्रोग्रामर की तुलना में कहीं अधिक सावधानीपूर्वक की है। ;) बेशक, इस कोड को इस विशिष्ट विवरण पर निर्भर न करें। – BoffinbraiN

उत्तर

1

हम Component.dispatchEventImpl से डिबगिंग शुरू करने के लिए की जरूरत है।
बस विधि की स्रोत टिप्पणियों के माध्यम से पढ़ने से आपको स्विंग में घटनाओं का प्रवाह करने का सही विचार मिलना चाहिए (आप EventQueue.pumpEventsForHeirarchy से एक स्तर भी शुरू कर सकते हैं)।

स्पष्टता के लिए सिर्फ मेरे कोड से एक उद्धरण दे:

  1. सेट टाइमस्टैम्प और वर्तमान घटना के संशोधक .; पूर्व प्रेषकों। AWTEventListeners को सूचित करने से पहले यहां कोई आवश्यक रीटाइक्लिंग/रीडरिंग करें।
  2. टूलकिट को इस ईवेंट को AWTEventListeners को पास करने दें।
  3. यदि कोई भी कोई महत्वपूर्ण ईवेंट नहीं लेता है, तो कीबोर्डफोकस प्रबंधक इसे संसाधित करने की अनुमति देता है।
  4. इनपुट विधियों घटना
  5. पूर्व प्रक्रिया वितरण
  6. से पहले किसी भी विशेष आयोजनों के सामान्य प्रक्रिया के लिए घटना उद्धार कार्रवाई करने के लिए अनुमति दें
  7. 4061116 के लिए एक विशिष्ट तरीका:। ब्राउज़र मोडल संवाद को बंद करने के लिए हुक :)
  8. पीयर को घटना को संसाधित करने दें। KeyEvents को छोड़कर, वे सब KeyEventPostProcessors के बाद साथियों के द्वारा कार्रवाई की जाएगी (देखें DefaultKeyboardFocusManager.dispatchKeyEvent())

अब आप अपने विवरण के साथ ऊपर प्रवाह का अधिकार है या नहीं, यह निर्धारित करने के मिलान कर सकते हैं। लेकिन मुद्दा यह है कि आपको वास्तव में निजी वर्गों के जावडॉक्स पर निर्भर नहीं होना चाहिए, कारण यह है कि डेवलपर्स आमतौर पर कोड बदलते समय निजी कक्षाओं की टिप्पणियों को अपडेट करने की परवाह नहीं करते हैं, इसलिए दस्तावेज़ अप्रचलित हो सकते हैं।

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