Java - 代码编译但动作未被识别

Java - Code compiles but action is not recognised

由于焦点问题,我在 Java 中遇到了一些关键侦听器问题,所以我阅读了相关内容,许多网站建议改用键绑定。 我的代码在下面,我正在尝试将 space 键映射到动作 TestAction。面板对象只是 JPanel 的扩展。

public class Template_Main {

static Boolean quit = false; 

public static void main(String[] args) {    
    Window window = new Window();
    while(!quit) {
        window.update();
    }
    System.exit(0);
}

}

.

import java.awt.Image;
import java.awt.Toolkit;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.KeyStroke;

public class Window {

public Frame frame;
public Panel panel;

public Window() {   
    frame = new Frame();
    panel = new Panel();    

    Action pressedAction = new TestAction();
    Action releasedAction = new TestAction();

    pressedAction.setEnabled(true);
    releasedAction.setEnabled(true);

    panel.getInputMap().put(KeyStroke.getKeyStroke("SPACE"),"pressed");
    panel.getInputMap().put(KeyStroke.getKeyStroke("released SPACE"),"released");

    panel.getActionMap().put("pressed",pressedAction);
    panel.getActionMap().put("released",releasedAction);

    frame.add(panel);
    frame.pack();
}

public void update() {
    Logic.update();
    updateImages();
    sleep();
}

public void updateImages() {
    panel.removeAll();
    for (int i = 0; i < Imgs.array.size(); ++i) {
        Img img = Imgs.get(i);
        addImage(img.name, img.x, img.y, img.width, img.height);
    }
    panel.repaint();
}

public void addImage(String name, int x, int y, int width, int height) {
    panel.add(newImageLabel(name, x, y, width, height));
}

public static JLabel newImageLabel(String imageName, int x, int y, int width, int height) {
    Toolkit toolkit = Toolkit.getDefaultToolkit();
    java.net.URL iconUrl = ClassLoader.getSystemResource("resources/"+imageName);
    Image image = toolkit.createImage(iconUrl);
    JLabel label = new JLabel(new ImageIcon(image));
    label.setBounds(x, y, width, height);
    return label;
}

static void sleep() {
    try {
        Thread.sleep(Math.round(10));
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

}

.

import javax.swing.JFrame;

public class Frame extends JFrame {

public Frame() {
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setTitle(Config.TITLE);
    setResizable(Config.RESIZABLE);
    setVisible(true);
}

}

.

import java.awt.Dimension;
import javax.swing.JPanel;

public class Panel extends JPanel {

public Panel() {
    setPreferredSize(new Dimension(Config.WIDTH,Config.HEIGHT));
    setLayout(null);
    setBackground(Config.BG_COLOR);
    setFocusable(true);
}

}

.

import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;

public class TestAction extends AbstractAction {

public TestAction() {

}

@Override
public void actionPerformed(ActionEvent arg0) {
    System.out.println("ACTION PERFORMED");
}

}

问题是虽然它编译没有错误,但当我按下 space 栏时没有任何反应。

我认为您的问题正如 William Morrison 在 JPanel 未获得焦点时所说的那样。

尝试在添加面板时调用 requestFocus()。如果您可以 post 一个包含的小代码示例,我们可以为您提供更多帮助。

以您的代码为基础,这有效。

import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;

public class App extends JFrame
{

    public static void main( String args[] )
    {
        new App();
    }

    public App()
    {
        super( "Test App" );
        setLocationRelativeTo( null );
        setSize( 600, 450 );
        setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        getContentPane().add( new KeyBindingPane() );
        setVisible( true );
    }

    private class KeyBindingPane extends JPanel
    {
        public KeyBindingPane()
        {
            this.getInputMap().put( KeyStroke.getKeyStroke( "SPACE" ), "pressed" );
            this.getInputMap().put( KeyStroke.getKeyStroke( "released SPACE" ), "released" );

            getActionMap().put( "pressed", new SpaceBarAction() );
            getActionMap().put( "released", new SpaceBarAction() );

            requestFocus();
        }
    }

    public class SpaceBarAction extends AbstractAction
    {
        @Override
        public void actionPerformed( ActionEvent e )
        {
            System.out.println( "ACTION PERFORMED (SPACE BAR)" );
        }
    }
}

感谢大家的帮助!

你是对的,面板没有聚焦,包含它的框架才是。 添加 panel.requestFocus(); 修复它!