JFrame के लिए गैर-जिम्मेदार KeyListener


80

मैं KeyListenerअपने लिए लागू करने की कोशिश कर रहा हूं JFrame। कंस्ट्रक्टर पर, मैं इस कोड का उपयोग कर रहा हूं:

System.out.println("test");
addKeyListener(new KeyListener() {
    public void keyPressed(KeyEvent e) { System.out.println( "tester"); }

    public void keyReleased(KeyEvent e) { System.out.println("2test2"); }

    public void keyTyped(KeyEvent e) { System.out.println("3test3"); }
});

जब मैं इसे चलाता हूं, तो testसंदेश मेरे कंसोल में आता है। हालांकि, जब मैं एक कुंजी दबाता हूं, तो मुझे कोई अन्य संदेश नहीं मिलता है, जैसे KeyListenerकि वहां भी नहीं था।

मैं सोच रहा था कि यह हो सकता है क्योंकि ध्यान केंद्रित नहीं है JFrame
और इसलिए वे KeyListenerकिसी भी घटना को प्राप्त नहीं करते हैं। लेकिन, मुझे पूरा यकीन है कि यह है।

क्या मुझे याद आ रही है कि वहाँ कुछ है?

जवाबों:


51

आपको अपने keyListener को हर उस घटक में जोड़ना होगा जिसकी आपको आवश्यकता है। केवल फ़ोकस वाले घटक ही इन घटनाओं को भेजेंगे। उदाहरण के लिए, यदि आपके JFrame में केवल एक TextBox है, तो उस TextBox का ध्यान केंद्रित है। तो आपको इस घटक के साथ एक KeyListener भी जोड़ना होगा।

प्रक्रिया समान है:

myComponent.addKeyListener(new KeyListener ...);

नोट: कुछ घटक JLabel की तरह फ़ोकस करने योग्य नहीं हैं।

उन्हें ध्यान देने योग्य बनाने के लिए आपको निम्न की आवश्यकता है:

myComponent.setFocusable(true);

2
हाँ, आप सही थे, जब प्रोग्राम शुरू होता है तो आप थोड़ा यह देख सकते हैं कि फोकस बटन पर है। प्रत्येक बटन के लिए एक कुंजी सूची को जोड़ने पर यह तय होता है। थोड़ा अजीब है, मुझे लगता है कि JFrame के लिए एक keylistener जोड़ने काम करेगा, लेकिन मुझे नहीं लगता। धन्यवाद!
टोमेक

मैंने JFrame पर एक श्रोता बनाया है जो कीबोर्ड से सुनता है। मैं इसे निष्क्रिय मोड में काम करना चाहता हूं, भले ही खिड़की सामने (केंद्रित) न हो। JFrame पैसिव मोड में नहीं सुन रहा है।
उस्मान

133

यदि आप प्रत्येक घटक पर एक श्रोता को पंजीकृत नहीं करना चाहते हैं,
तो आप अपना खुदKeyEventDispatcher का जोड़ सकते हैंKeyboardFocusManager :

public class MyFrame extends JFrame {    
    private class MyDispatcher implements KeyEventDispatcher {
        @Override
        public boolean dispatchKeyEvent(KeyEvent e) {
            if (e.getID() == KeyEvent.KEY_PRESSED) {
                System.out.println("tester");
            } else if (e.getID() == KeyEvent.KEY_RELEASED) {
                System.out.println("2test2");
            } else if (e.getID() == KeyEvent.KEY_TYPED) {
                System.out.println("3test3");
            }
            return false;
        }
    }
    public MyFrame() {
        add(new JTextField());
        System.out.println("test");
        KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
        manager.addKeyEventDispatcher(new MyDispatcher());
    }

    public static void main(String[] args) {
        MyFrame f = new MyFrame();
        f.pack();
        f.setVisible(true);
    }
}

5
KeyboardFocusManager एप्लिकेशन वाइड है, यदि आपके पास मल्टी फ्रेम हैं, तो आपको परेशानी होगी?
नवदमुंड

2
तो यह काम करना चाहिए, कुछ इस तरह से: foreach ("फ्रेम में ध्यान देने योग्य घटक" _) के रूप में {_.addkeylistener (frameKeylistener);}
neoedmund

16

InputMaps और ActionMaps को घटक, यह और इसके सभी उप-घटकों या संपूर्ण विंडो के लिए प्रमुख घटनाओं को पकड़ने के लिए डिज़ाइन किया गया था। इसे JComponent.getInputMap () में पैरामीटर के माध्यम से नियंत्रित किया जाता है। प्रलेखन के लिए कुंजी बिन्दुओं का उपयोग कैसे करें देखें ।

इस डिजाइन की सुंदरता यह है कि कोई भी चुन सकता है और कौन से स्ट्रोक की निगरानी करना महत्वपूर्ण है और उन कुंजी स्ट्रोक के आधार पर अलग-अलग कार्रवाई की गई है।

यह कोड एक JFrame पर डिस्पोज () कॉल करेगा जब विंडो में कहीं भी भागने की कुंजी हिट होती है। JFrame JComponent से नहीं निकलता है इसलिए आपको कुंजी बंधन बनाने के लिए JFrame में एक और घटक का उपयोग करना होगा। सामग्री फलक एक ऐसा घटक हो सकता है।

InputMap inputMap; 
ActionMap actionMap;
AbstractAction action;
JComponent component;

inputMap  = component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
actionMap = component.getActionMap();

action    = new AbstractAction()
{
   @Override
   public void actionPerformed(ActionEvent e)
   {
      dispose();
   }
};

inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "dispose");
actionMap.put("dispose", action);

10

KeyListenerनिम्न स्तर है और केवल एक घटक पर लागू होता है। इसे और अधिक प्रयोग करने योग्य बनाने के प्रयासों के बावजूद JFrame, कई घटक घटक बनते हैं, सबसे स्पष्ट सामग्री फलक।JComboBoxयूआई भी अक्सर एक समान तरीके से लागू किया जाता है।

यह महत्वपूर्ण घटनाओं के लिए थोड़ा अलग तरीके से माउस घटनाओं को ध्यान देने योग्य है।

आपको क्या करना चाहिए, इस बारे में विस्तार से जानकारी के लिए एप्लिकेशन वाइड कीबोर्ड शॉर्टकट - जावा स्विंग पर मेरा उत्तर देखें ।


10

मुझे वही समस्या मिली जब तक मैंने पढ़ा कि असली समस्या FOCUS के बारे में है, आपका JFrame पहले ही श्रोताओं को जोड़ चुका है, लेकिन टूर फ़्रेम फ़ोकस पर नहीं है क्योंकि आपको अपने JFrame के अंदर बहुत सारे घटक मिले हैं, जो फ़ोकस करने योग्य भी हैं:

JFrame.setFocusable(true);

शुभ लाभ


2
मैंने पाया कि यह केवल तब तक काम करता है जब तक मैं अपने JFrame पर कुछ का उपयोग नहीं करता, तब KeyListener अब जवाब नहीं देता
user3328784

9

डियोन (और किसी और से एक समान प्रश्न पूछते हैं), आप ऊपर दिए गए पीटर के कोड का उपयोग कर सकते हैं लेकिन मानक आउटपुट पर प्रिंट करने के बजाय, आप कुंजी कोड के लिए परीक्षण करते हैं, रोका, या टाइप किया।

@Override
public boolean dispatchKeyEvent(KeyEvent e) {
    if (e.getID() == KeyEvent.KEY_PRESSED) {
        if (e.getKeyCode() == KeyEvent.VK_F4) {
            dispose();
        }
    } else if (e.getID() == KeyEvent.KEY_RELEASED) {
        if (e.getKeyCode() == KeyEvent.VK_F4) {
            dispose();
        }
    } else if (e.getID() == KeyEvent.KEY_TYPED) {
        if (e.getKeyCode() == KeyEvent.VK_F4) {
            dispose();
        }
    }
    return false;
}

4

JFrame में सभी टेक्स्ट फ़ील्ड की प्रमुख घटनाओं को कैप्चर करने के लिए , एक महत्वपूर्ण इवेंट पोस्ट प्रोसेसर को नियोजित कर सकता है। यहाँ आप स्पष्ट रूप से शामिल करने के बाद एक काम कर रहे उदाहरण है।

public class KeyListenerF1Demo extends JFrame implements KeyEventPostProcessor {
    public static final long serialVersionUID = 1L;

    public KeyListenerF1Demo() {
        setTitle(getClass().getName());

        // Define two labels and two text fields all in a row.
        setLayout(new FlowLayout());

        JLabel label1 = new JLabel("Text1");
        label1.setName("Label1");
        add(label1);

        JTextField text1 = new JTextField(10);
        text1.setName("Text1");
        add(text1);

        JLabel label2 = new JLabel("Text2");
        label2.setName("Label2");
        add(label2);

        JTextField text2 = new JTextField(10);
        text2.setName("Text2");
        add(text2);

        // Register a key event post processor.
        KeyboardFocusManager.getCurrentKeyboardFocusManager()
                .addKeyEventPostProcessor(this);
    }

    public static void main(String[] args) {
        JFrame f = new KeyListenerF1Demo();
        f.setName("MyFrame");
        f.pack();
        f.setVisible(true);
    }

    @Override
    public boolean postProcessKeyEvent(KeyEvent ke) {
        // Check for function key F1 pressed.
        if (ke.getID() == KeyEvent.KEY_PRESSED
                && ke.getKeyCode() == KeyEvent.VK_F1) {

            // Get top level ancestor of focused element.
            Component c = ke.getComponent();
            while (null != c.getParent())
                c = c.getParent();

            // Output some help.
            System.out.println("Help for " + c.getName() + "."
                    + ke.getComponent().getName());

            // Tell keyboard focus manager that event has been fully handled.
            return true;
        }

        // Let keyboard focus manager handle the event further.
        return false;
    }
}

एक कामकाजी उदाहरण के लिए आप आयात को जोड़ने पर विचार कर सकते हैं। मैं आमतौर पर उन्हें कम रखने के लिए 'पैकेज आयात' जोड़ता हूं। अन्यथा, +1। दिलचस्प तकनीक।
एंड्रयू थॉम्पसन

2

हम्म .. आपकी रचना किस वर्ग के लिए है? शायद कुछ वर्ग JFrame का विस्तार कर रहे हैं? खिड़की का फोकस खिड़की पर होना चाहिए, लेकिन मुझे नहीं लगता कि यह समस्या है।

मैंने आपके कोड का विस्तार किया, इसे चलाने की कोशिश की और इसने काम किया - कुंजी प्रेस के परिणामस्वरूप प्रिंट आउटपुट मिला। (ग्रहण के माध्यम से उबंटू के साथ चलाएं):

public class MyFrame extends JFrame {
    public MyFrame() {
        System.out.println("test");
        addKeyListener(new KeyListener() {
            public void keyPressed(KeyEvent e) {
                System.out.println("tester");
            }

            public void keyReleased(KeyEvent e) {
                System.out.println("2test2");
            }

            public void keyTyped(KeyEvent e) {
                System.out.println("3test3");
            }
        });
    }

    public static void main(String[] args) {
        MyFrame f = new MyFrame();
        f.pack();
        f.setVisible(true);
    }
}

मुझे सभी संदेश आउटपुट भी मिलते हैं। विंडोज कमांड लाइन में चलाएं।
डारेल

2
आपको सभी संदेश मिलते हैं क्योंकि इस उदाहरण में JFrame का फोकस है। JFrame में एक TextBox घटक जोड़ने की कोशिश करें और देखें कि क्या होता है।
ब्रूनो कोंडे

2

यह मदद करनी चाहिए

    yourJFrame.setFocusable(true);
    yourJFrame.addKeyListener(new java.awt.event.KeyAdapter() {


        @Override
        public void keyTyped(KeyEvent e) {
            System.out.println("you typed a key");
        }

        @Override
        public void keyPressed(KeyEvent e) {
            System.out.println("you pressed a key");
        }

        @Override
        public void keyReleased(KeyEvent e) {
            System.out.println("you released a key");
        }
    });

1

मुझे भी यही समस्या आ रही है। मैंने आपके लिए ब्रूनो की सलाह का पालन किया और पाया कि जेफ्रेम (यानी, ऊपर बाईं तरफ) में "पहले" बटन के साथ एक KeyListener को जोड़कर चाल चली। लेकिन मैं आपसे सहमत हूं कि यह एक सुलझा हुआ समाधान है। इसलिए मैंने चारों ओर फिड किया और इसे ठीक करने के लिए एक भोजनालय की खोज की। बस लाइन जोड़ें

myChildOfJFrame.requestFocusInWindow();

अपनी मुख्य विधि के बाद, आपने JFrame के अपने उपवर्ग का अपना उदाहरण बनाया है और इसे दिखाई दे रहा है।


धन्यवाद, एक ही समस्या थी। अजीब तरह से घटक ध्यान केंद्रित खो देता है भले ही वह सामग्री फलक हो ...
Androbin

-3

योग्य .... आपको बस इतना करना है कि सुनिश्चित करें

addKeyListener (यह);

आपके कोड में सही तरीके से रखा गया है।


8
आपको इसे एक उपयोगी उत्तर बनाने के लिए वास्तव में "सही जगह" समझाना चाहिए।
तक

-3

आप अपने JFrame को अपने माता-पिता JFrame को ध्यान में रखते हुए कस्टम JCompords सेट कर सकते हैं।

बस एक कंस्ट्रक्टर जोड़ें और JFrame में पास करें। फिर paintComponent में setFocusable () के लिए कॉल करें।

इस तरह JFrame हमेशा KeyEvents प्राप्त करेगा चाहे अन्य घटकों को दबाया जाए।


4
-1 निश्चित रूप से नहीं - यह पूरा हो गया है <एक से अधिक सम्मान में मजबूत शब्द> सेंसर: क) अश्लील उपहास ख) अश्लील संदर्भ गुजरते हुए ग) अनुचित राज्य परिवर्तन पेंटिंग करते हुए घ) ..
क्लियोपेट्रा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.