1

重複して申し訳ありません-これを書いたときは急いでいて、確認する時間がありませんでした。今思えばもっと早かったのに…。


重複の可能性:
JFrame の Java KeyListener が応答しませんか?

私はアプリを書いていて、ホットキーを作ろうとしています。を使用することにしKeyListenerました。これは、まだ私が知っているすべてです。ただし、クラスはキーの押下に応答していません。このバグを修正するにはどうすればよいですか? 同じことを行う代替手段がある場合は、KeyListener私に知らせてください。できれば、それがどのように機能するかの例を提供してください。

メインクラス

import java.awt.BorderLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.*;
import panels.TabBar;

public class __mn implements KeyListener {
    static JFrame disp = new JFrame("dat app");

    static TabBar tabs = new TabBar();

    public static void main(String[] args) {
        disp.setLayout(new BorderLayout());
        disp.add(tabs, BorderLayout.PAGE_START);
        disp.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        disp.setSize(TabBar.PREF_WIDTH, 500);
        disp.setResizable(false);
        disp.setLocationRelativeTo(null);
        disp.addKeyListener(new __mn());
        disp.setVisible(true);
    }

    @Override
    public void keyPressed(KeyEvent e) {
        System.out.println(e.paramString());
    }

    //Unused
    @Override public void keyReleased(KeyEvent e) {
        System.out.println(e.paramString());
    } 
    @Override public void keyTyped(KeyEvent e) {
        System.out.println(e.paramString());
    }
}

TabBar クラス

package panels;

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;

//http://www.dreamincode.net/forums/topic/245148-java-key-binding-tutorial-and-demo-program/

public class TabBar extends JPanel implements ActionListener {
    private static final long serialVersionUID = 1L;

    public static final int NONE = -1;
    public static final int INBOX = 0;
    public static final int SEND_MSG = 1;
    public static final int PRIVATE_CHAT = 2;
    public static final int FEEDBACK = 3;

    public static final int PREF_WIDTH = 425;

    private static final String[] tabNames = {"Inbox", "Send a message", "Private chat", "Feedback"};

    private static final JButton btnInbox = new JButton(tabNames[INBOX]);
    private static final JButton btnSendMSG = new JButton(tabNames[SEND_MSG]);
    private static final JButton btnPrivChat = new JButton(tabNames[PRIVATE_CHAT]);
    private static final JButton btnFeedback = new JButton(tabNames[FEEDBACK]);

    public int currentTab = -1;

    public TabBar() {
        this(new FlowLayout());
    }

    public TabBar(LayoutManager layout) {
        super(layout);

        add(btnInbox);
        add(btnSendMSG);
        add(btnPrivChat);
        add(btnFeedback);

        btnInbox.addActionListener(this);
        btnSendMSG.addActionListener(this);
        btnPrivChat.addActionListener(this);
        btnFeedback.addActionListener(this);

        setBackground(Color.BLACK);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println(e.paramString());
        if (e.getSource() == btnInbox)
            currentTab = INBOX;
        else if (e.getSource() == btnSendMSG)
            currentTab = SEND_MSG;
        else if (e.getSource() == btnPrivChat)
            currentTab = PRIVATE_CHAT;
        else if (e.getSource() == btnFeedback)
            currentTab = FEEDBACK;
        else currentTab = NONE;
    }

    public void hotkeyPressed(char pressed) {
        pressed = Character.toLowerCase(pressed);
        System.out.println("Hotkey pressed: " + pressed);
        switch (pressed) {
        case 'i':
            setTab(INBOX);
            break;
        case 's':
            setTab(SEND_MSG);
            break;
        case 'p':
            setTab(PRIVATE_CHAT);
            break;
        case 'f':
            setTab(FEEDBACK);
            break;
        default:
            break;
        }
    }

    private void setTab(int tab) {
        System.out.println("Somthing pressed! tab=" + tab);
        currentTab = tab;
        switch (tab) {
        case INBOX:
            btnInbox.requestFocusInWindow();
        }
    }
}
4

2 に答える 2

4

このバグを修正するにはどうすればよいですか?

非互換性ほどバグではありません。

同じことを行う KeyListener の代替手段がある場合は、私に知らせてください。できれば、それがどのように機能するかの例を提供してください。

フォーカスの問題があるため、KeyListener/を Swing コンポーネントに使用しないでください。これは、コンポーネントが表示された後にコンポーネントを呼び出してフォーカスがあることを確認することで回避できます。KeyAdapterrequestFocusInWindow()setFoucsable(true);JLabel

Swing コンポーネントはKeyBindingsを使用する必要があります。これは、追加さsetFocusable(true)れたコンポーネントなどを自動的に呼び出すことにより、上記の問題を克服します。KeyBinding

以下に小さな例を示します。

void addKeyBinding(JComponent jc) {
        jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, false), "A pressed");
        jc.getActionMap().put("esc pressed", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                System.out.println("A pressed");
            }
        });

        jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, true), "A released");
        jc.getActionMap().put("A released", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                System.out.println("A released");
            }
        });
}

追加したいJComponentieなどのインスタンスを指定してこのメ​​ソッドを呼び出します。JPanelKeybinding

JPanel p=new JPanel();

addKeyBinding(p);

コードに関するその他の提案:

  • 常に Swing コンポーネントをEvent Dispatch ThreadviaSwingUtilities.invokeXXXブロックに作成する

  • このクラスがonlyとして使用される場合、または実装するクラス/メソッドを他のクラスに公開する場合を除き、クラス自体にListenerlikeを実装しないでください。ActionListenerListener Listeners

于 2013-01-08T19:33:10.703 に答える
2

JFrame は多くの異なるコンポーネントで構成されているため、本質的にフォーカス可能ではありません。フォーカスがないと、キー イベントを受け取ることができません。これには多くの解決策があります。私はこれを提案するだけです:

JFrame の応答しない KeyListener

そして、「jframe Javaのキーリスナー」をグーグルで検索して、詳細を見つけることをお勧めします。私が言ったように、この問題に取り組む方法はたくさんあります。

于 2013-01-08T18:27:27.167 に答える