سؤال

وأنا أحاول أن تنفيذ 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"); }
});

عند I تشغيله، رسالة test تأتي في وحدة بلدي. ومع ذلك، عند الضغط على مفتاح، أنا لا أحصل على أي من رسائل أخرى، كما لو كان KeyListener ولا حتى هناك.

وكنت أفكر أنه يمكن أن يكون ذلك بسبب التركيز ليس على JFrame و
وحتى KeyListener لا تتلقى أية أحداث. ولكن، وأنا متأكد من ذلك.

هل هناك شيء أنا في عداد المفقودين؟

هل كانت مفيدة؟

المحلول

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

وهذه العملية هي نفسها:

myComponent.addKeyListener(new KeyListener ...);

ملحوظة: بعض المكونات ليست focusable من مثل JLabel

.

لوضع لهم القابل للتركيز تحتاج إلى:

myComponent.setFocusable(true);

نصائح أخرى

إذا كنت لا تريد تسجيل المستمع على كل عنصر،
هل يمكن على إضافة 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);
    }
}

وصممت 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);

وKeyListener هو مستوى منخفض وينطبق فقط على مكون واحد. على الرغم من المحاولات لجعله أكثر قابلية للاستخدام JFrame يخلق عددا من العناصر المكونة، أبرزها جزء المحتوى. أيضا غالبا ما تنفذ JComboBox UI بطريقة مماثلة.

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

لمزيد من التفاصيل حول ما يجب عليك القيام به، انظر جوابي على تطبيق لوحة المفاتيح واسعة الاختصار - جافا سوينغ

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

JFrame.setFocusable(true);

وحظا سعيدا

وDeion (وغيرهم طرح سؤال مماثل)، هل يمكن استخدام كود بطرس أعلاه ولكن بدلا من الطباعة إلى الإخراج القياسي، يمكنك اختبار لرمز مفتاح ضغط، يطلق، أو كتابتها.

@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;
}

ومن أجل القبض على الأحداث الرئيسية ALL حقول النص في 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;
    }
}

وهم .. ما هو الطبقة منشئ الخاصة بك؟ ربما بعض الطبقة تمتد 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);
    }
}

وهذا من شأنه أن يساعد

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

ولقد كان لديها نفس المشكلة. تابعت المشورة برونو لك ووجد أن إضافة KeyListener فقط على زر "الأول" في JFrame (أي في أعلى يسار) لم الحيلة. ولكن أنا أتفق معك أنه نوع من الحل المقلقة. لذلك أنا مغشوش حول واكتشفت وسيلة أكثر إتقانا لتصحيح الامر. فقط إضافة سطر

myChildOfJFrame.requestFocusInWindow();

وعلى طريقة الرئيسي الخاص بك، بعد إنشاء مثيل من فئة فرعية الخاص بك من JFrame وضعه مرئية.

ولول .... كل ما عليك القيام به هو التأكد من أن

وaddKeyListener (هذا)؛

ويتم وضعها بشكل صحيح في التعليمات البرمجية.

ضبط

هل يمكن أن يكون JComponents مخصص الأم JFrame القابل للتركيز.

وأضيف منشئ وتمرير في JFrame. ثم إجراء مكالمة إلى setFocusable () في paintComponent.

وهذه الطريقة سوف JFrame تلقي دائما KeyEvents بغض النظر عما إذا ضغطت المكونات الأخرى.

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