簡體   English   中英

JFrame的KeyListener沒有響應

[英]Unresponsive KeyListener for JFrame

我正在嘗試為JFrame實現KeyListener 在構造函數上,我使用以下代碼:

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不會收到任何事件。 但是,我很確定。

有什么我想念的嗎?

如果您不想在每個組件上注冊一個偵聽器,
您可以將自己的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);
    }
}

您必須將keyListener添加到所需的每個組件中。 僅具有焦點的組件將發送這些事件。 例如,如果JFrame中只有一個TextBox,則該TextBox具有焦點。 因此,您還必須將KeyListener添加到此組件。

過程是一樣的:

myComponent.addKeyListener(new KeyListener ...);

注意:某些組件無法像JLabel那樣聚焦。

要將它們設置為可聚焦,您需要:

myComponent.setFocusable(true);

InputMap和ActionMap旨在捕獲組件,組件及其所有子組件或整個窗口的鍵事件。 這是通過JComponent.getInputMap()中的參數控制的。 有關文檔,請參見如何使用鍵綁定

此設計的優點在於,可以選擇並選擇哪些按鍵對於監視非常重要,並根據這些按鍵觸發不同的動作。

當在窗口中的任意位置按下轉義鍵時,此代碼將在JFrame上調用dispose()。 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通常也以類似的方式實現。

值得注意的是,鼠標事件的工作方式與鍵事件略有不同。

有關應執行的操作的詳細信息,請參見我關於應用程序級鍵盤快捷鍵-Java Swing的答復。

我遇到了同樣的問題,直到我讀到真正的問題是關於FOCUS的問題為止,您的JFrame已經添加了偵聽器,但是巡視框架從來沒有放在Focus上,因為您在JFrame中擁有很多可以聚焦的組件,所以請嘗試:

JFrame.setFocusable(true);

祝好運

Deion(以及其他提出類似問題的人),您可以使用上面的Peter的代碼,但是可以打印關鍵代碼PRESSED,RELEASED或TYPED,而不是打印到標准輸出。

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

為了捕獲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;
    }
}

這應該有幫助

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

嗯..您的構造函數是什么類的? 可能是一些擴展JFrame的類? 當然,窗口焦點應該在窗口上,但是我不認為這是問題所在。

我擴展了您的代碼,嘗試運行它並成功了-按鍵結果作為打印輸出。 (通過Eclipse與Ubuntu一起運行):

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

我一直有同樣的問題。 我聽了Bruno的建議,發現僅在JFrame中的“第一個”按鈕(即,左上方)上添加KeyListener就可以了。 但是我同意你的看法,這是一個令人不安的解決方案。 所以我四處弄弄,發現了一種更整潔的方法來修復它。 只需添加行

myChildOfJFrame.requestFocusInWindow();

創建主JFrame子類的實例並將其設置為可見后,將其轉換為主要方法。

大聲笑..您要做的就是確保

addKeyListener(this);

已正確放置在您的代碼中。

您可以讓自定義JComponent將其父JFrame設置為可聚焦。

只需添加一個構造函數並傳遞JFrame。 然后在paintComponent中調用setFocusable()。

這樣,無論是否按下其他組件,JFrame都將始終接收KeyEvent。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM