Pertanyaan KeyListener tidak responsif untuk JFrame


Saya mencoba menerapkan KeyListener untuk ku JFrame. Pada konstruktor, saya menggunakan kode ini:

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

Saat saya menjalankannya, test pesan muncul di konsol saya. Namun, ketika saya menekan tombol, saya tidak mendapatkan salah satu dari pesan lainnya, seolah-olah KeyListener bahkan tidak ada di sana.

Saya berpikir bahwa itu mungkin karena fokusnya bukan pada JFrame
dan mereka KeyListener tidak menerima kejadian apa pun. Tapi, aku yakin itu.

Apakah ada sesuatu yang saya hilang?


75
2017-11-13 10:17


asal


Jawaban:


Anda harus menambahkan keyListener Anda ke setiap komponen yang Anda butuhkan. Hanya komponen dengan fokus yang akan mengirim peristiwa ini. Misalnya, jika Anda hanya memiliki satu TextBox di JFrame Anda, TextBox itu memiliki fokus. Jadi Anda harus menambahkan KeyListener ke komponen ini juga.

Prosesnya sama:

myComponent.addKeyListener(new KeyListener ...);

Catatan: Beberapa komponen tidak fokus seperti JLabel.

Untuk mengaturnya agar dapat fokus, Anda perlu:

myComponent.setFocusable(true);

46
2017-11-13 13:01



Jika Anda tidak ingin mendaftar pendengar pada setiap komponen,
Anda bisa tambahkan milik Anda KeyEventDispatcher ke 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);
    }
}

125
2017-09-04 14:09



InputMaps dan ActionMaps dirancang untuk menangkap peristiwa utama untuk komponen, itu dan semua sub-komponennya, atau seluruh jendela. Ini dikontrol melalui parameter di JComponent.getInputMap (). Lihat Cara Menggunakan Binding Kunci untuk dokumentasi.

Keindahan dari desain ini adalah bahwa seseorang dapat memilih dan memilih stroke kunci mana yang penting untuk dipantau dan memiliki tindakan yang berbeda yang dipicu berdasarkan pukulan kunci tersebut.

Kode ini akan memanggil buang () pada JFrame ketika tombol pelarian dipukul di mana saja di jendela. JFrame tidak berasal dari JComponent jadi Anda harus menggunakan komponen lain di JFrame untuk membuat kunci yang mengikat. Panel konten mungkin komponen seperti itu.

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

15
2018-02-23 00:29



KeyListener tingkat rendah dan hanya berlaku untuk komponen tunggal. Meskipun upaya untuk membuatnya lebih bermanfaat JFrame membuat sejumlah komponen komponen, yang paling jelas adalah panel konten. JComboBox UI juga sering diimplementasikan dengan cara yang serupa.

Perlu dicatat bahwa acara mouse bekerja dengan cara yang aneh sedikit berbeda dengan peristiwa penting.

Untuk detail tentang apa yang harus Anda lakukan, lihat jawaban saya di Pintasan keyboard lebar aplikasi - Java Swing.


10
2017-11-13 13:18



Saya memiliki masalah yang sama sampai saya membaca bahwa masalah sebenarnya adalah tentang FOCUS karena JFrame Anda telah menambahkan Listeners tetapi frame tur tidak pernah di Focus karena Anda mendapatkan banyak komponen di dalam JFrame Anda yang juga dapat di-focus jadi coba:

JFrame.setFocusable(true);

Semoga berhasil


10
2018-04-27 15:30



Deion (dan siapa pun yang mengajukan pertanyaan serupa), Anda dapat menggunakan kode Peter di atas tetapi alih-alih mencetak ke output standar, Anda menguji kode kunci yang DIKETAHUI, DIBATALKAN, atau DIKETAHUI.

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

8
2018-01-09 14:50



untuk menangkap peristiwa utama dari SEMUA bidang teks di a JFrame, seseorang dapat menggunakan prosesor pasca kejadian kunci. Berikut ini contoh kerja, setelah Anda menambahkan termasuk yang jelas.

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

4
2017-07-15 19:47



Hmm .. untuk apa kelas konstruktor Anda? Mungkin beberapa kelas memperluas JFrame? Fokus jendela seharusnya berada di jendela, tentu saja tetapi saya tidak berpikir itulah masalahnya.

Saya memperluas kode Anda, mencoba menjalankannya dan itu berhasil - tombol ditekan sebagai output cetak. (dijalankan dengan Ubuntu melalui Eclipse):

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

3
2017-11-13 10:39