मैंने कुछ बार 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 से है।)
यह KeyEvent हैंडलिंग पर एक अच्छा विश्लेषण है ... लेकिन मुझे नहीं पता कि यह वास्तव में एक प्रश्न है जो उत्तरदायी है। – BoffinbraiN
@BoffinbraiN: मुझे उम्मीद थी कुछ दर्जन स्विंग बैज के साथ किसी का कहना है कि कुछ की तरह "मेरी जानकारी के अनुसार यह सही है" :) –
हाँ, वह निश्चित रूप से बेहतर हो गया होता! लेकिन मुझे लगता है कि इस गहरे कुछ के लिए, यह वास्तव में कार्यान्वयन-विशिष्ट है, और आपने इस कार्यान्वयन की जांच अब तक की सबसे मेहनती प्रोग्रामर की तुलना में कहीं अधिक सावधानीपूर्वक की है। ;) बेशक, इस कोड को इस विशिष्ट विवरण पर निर्भर न करें। – BoffinbraiN