Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用键绑定同时运行代码块?_Java_Multithreading_Swing_Key Bindings - Fatal编程技术网

Java 如何使用键绑定同时运行代码块?

Java 如何使用键绑定同时运行代码块?,java,multithreading,swing,key-bindings,Java,Multithreading,Swing,Key Bindings,我目前正在学习如何使用密钥绑定。我在玩弄我写的代码,我注意到当我按下两个键(箭头键)时,只有最后一个会运行。我应该简单地使用KeyListener还是有办法让它工作?由于这是一个游戏,它必须能够运行超过4个键在同一时间 package game; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.ev

我目前正在学习如何使用密钥绑定。我在玩弄我写的代码,我注意到当我按下两个键(箭头键)时,只有最后一个会运行。我应该简单地使用KeyListener还是有办法让它工作?由于这是一个游戏,它必须能够运行超过4个键在同一时间

package game;


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;

import game.sfx.Screen;
import game.sfx.SpriteSheet;

public class Game implements Runnable{


    private static final long serialVersionUID = 1L;

    public static final int WIDTH = 160;
    public static final int HEIGHT = WIDTH / 12 * 9;
    public static final int SCALE = 3;
    public static final String NAME = "Game";

    private JFrame frame;
    private JPanel panel;

    public boolean running = false;
    public int tickCount = 0;

    private BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
    private int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();

    Screen screen;

    public Game(){
        panel = new JPanel();

        panel.setMinimumSize(new Dimension(WIDTH*SCALE, HEIGHT*SCALE));
        panel.setMaximumSize(new Dimension(WIDTH*SCALE, HEIGHT*SCALE));
        panel.setPreferredSize(new Dimension(WIDTH*SCALE, HEIGHT*SCALE));

        frame = new JFrame(NAME);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());

        frame.add(panel, BorderLayout.CENTER);
        frame.pack();

        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true); 

        InputMap im = panel.getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW); // key binding here
        ActionMap am = panel.getActionMap();

        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "r");
        am.put("r", new InputHandler("right", this));
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "l");
        am.put("l", new InputHandler("left", this));    
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "u");
        am.put("u", new InputHandler("up", this));  
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "d");
        am.put("d", new InputHandler("down", this));    

    }


    public void init(){
        screen = new Screen(WIDTH, HEIGHT, new SpriteSheet("res/Untitled.png"));
    }

    public synchronized void start() {
        running = true;
        new Thread(this).start();
    }

    public synchronized void stop() {
        running = false;
    }

    public void run() {     
        long lastTime = System.nanoTime();
        double nsPerTick = 1000000000D/60D;

        int frames = 0;
        int ticks = 0;

        long lastTimer = System.currentTimeMillis();
        double delta = 0;

        init();

        while (running){
            long now = System.nanoTime();
            delta += (now - lastTime) / nsPerTick;
            lastTime = now;
            boolean shouldRender = true;
            while(delta >= 1)
            {
                ticks++;
                tick();
                delta -= 1;
                shouldRender = true;
            }

            try {
                Thread.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if (shouldRender)
            {
                frames++;
                render();
            }

            if(System.currentTimeMillis() - lastTimer >= 1000){
                lastTimer += 1000;
                System.out.println(ticks + " ticks, " + frames + " frames");
                frames = 0;
                ticks = 0;
            }
        }
    }

    public void tick(){
        tickCount++;


    }

    public void render(){


        screen.render(pixels, 0, WIDTH);

        Graphics g = panel.getGraphics();

        g.drawImage(image, 0, 0, panel.getWidth(), panel.getHeight(), null);

        g.dispose();

    }

    public static void main(String[] args){ 
        new Game().start();     
    }

}

class InputHandler extends AbstractAction {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private String key;
    private Game game;


    public InputHandler(String key, Game game) {
        this.key = key;
        this.game = game;
    }


    @Override
    public void actionPerformed(ActionEvent e) {        
        switch(key){
        case "right": 
        game.screen.xOffset+=2;
        break;
        case "left": 
        game.screen.xOffset-=2;
        break;
        case "up": 
        game.screen.yOffset+=2;
        break;
        case "down": 
        game.screen.yOffset-=2;
        break;
        }

    }

}
这是代码

按照我的建议执行:

  • 使用摆动计时器创建游戏循环
  • 创建一个名为Direction的枚举,该枚举包含上、下、左和右项
  • 也有int向量场,表示实际的方向
  • 创建一个
    HashMap
    ,当按下箭头键时,它会被更改
  • 让游戏循环杆映射此地图,并根据哪个方向映射为Boolean.TRUE来改变方向
  • 设置密钥绑定,只需更改HashMap的状态即可
按照我的建议:

  • 使用摆动计时器创建游戏循环
  • 创建一个名为Direction的枚举,该枚举包含上、下、左和右项
  • 也有int向量场,表示实际的方向
  • 创建一个
    HashMap
    ,当按下箭头键时,它会被更改
  • 让游戏循环杆映射此地图,并根据哪个方向映射为Boolean.TRUE来改变方向
  • 设置密钥绑定,只需更改HashMap的状态即可
我注意到当我按下两个键(箭头键)时,只有最后一个键会运行

因为只为最后按下的键生成事件

我应该简单地使用KeyListener吗

无论您使用KeyListener还是KeyBindings,这都是正确的。它是生成事件的操作系统

由于这是一个游戏,它必须能够运行超过4个键在同一时间

package game;


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;

import game.sfx.Screen;
import game.sfx.SpriteSheet;

public class Game implements Runnable{


    private static final long serialVersionUID = 1L;

    public static final int WIDTH = 160;
    public static final int HEIGHT = WIDTH / 12 * 9;
    public static final int SCALE = 3;
    public static final String NAME = "Game";

    private JFrame frame;
    private JPanel panel;

    public boolean running = false;
    public int tickCount = 0;

    private BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
    private int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();

    Screen screen;

    public Game(){
        panel = new JPanel();

        panel.setMinimumSize(new Dimension(WIDTH*SCALE, HEIGHT*SCALE));
        panel.setMaximumSize(new Dimension(WIDTH*SCALE, HEIGHT*SCALE));
        panel.setPreferredSize(new Dimension(WIDTH*SCALE, HEIGHT*SCALE));

        frame = new JFrame(NAME);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());

        frame.add(panel, BorderLayout.CENTER);
        frame.pack();

        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true); 

        InputMap im = panel.getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW); // key binding here
        ActionMap am = panel.getActionMap();

        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "r");
        am.put("r", new InputHandler("right", this));
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "l");
        am.put("l", new InputHandler("left", this));    
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "u");
        am.put("u", new InputHandler("up", this));  
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "d");
        am.put("d", new InputHandler("down", this));    

    }


    public void init(){
        screen = new Screen(WIDTH, HEIGHT, new SpriteSheet("res/Untitled.png"));
    }

    public synchronized void start() {
        running = true;
        new Thread(this).start();
    }

    public synchronized void stop() {
        running = false;
    }

    public void run() {     
        long lastTime = System.nanoTime();
        double nsPerTick = 1000000000D/60D;

        int frames = 0;
        int ticks = 0;

        long lastTimer = System.currentTimeMillis();
        double delta = 0;

        init();

        while (running){
            long now = System.nanoTime();
            delta += (now - lastTime) / nsPerTick;
            lastTime = now;
            boolean shouldRender = true;
            while(delta >= 1)
            {
                ticks++;
                tick();
                delta -= 1;
                shouldRender = true;
            }

            try {
                Thread.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if (shouldRender)
            {
                frames++;
                render();
            }

            if(System.currentTimeMillis() - lastTimer >= 1000){
                lastTimer += 1000;
                System.out.println(ticks + " ticks, " + frames + " frames");
                frames = 0;
                ticks = 0;
            }
        }
    }

    public void tick(){
        tickCount++;


    }

    public void render(){


        screen.render(pixels, 0, WIDTH);

        Graphics g = panel.getGraphics();

        g.drawImage(image, 0, 0, panel.getWidth(), panel.getHeight(), null);

        g.dispose();

    }

    public static void main(String[] args){ 
        new Game().start();     
    }

}

class InputHandler extends AbstractAction {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private String key;
    private Game game;


    public InputHandler(String key, Game game) {
        this.key = key;
        this.game = game;
    }


    @Override
    public void actionPerformed(ActionEvent e) {        
        switch(key){
        case "right": 
        game.screen.xOffset+=2;
        break;
        case "left": 
        game.screen.xOffset-=2;
        break;
        case "up": 
        game.screen.yOffset+=2;
        break;
        case "down": 
        game.screen.yOffset-=2;
        break;
        }

    }

}
因此,解决方案是在按下/释放每个键时跟踪它

退房。
KeyboardAnimation
示例显示了如何使用键绑定来完成此操作

我注意到当我按下两个键(箭头键)时,只有最后一个键会运行

因为只为最后按下的键生成事件

我应该简单地使用KeyListener吗

无论您使用KeyListener还是KeyBindings,这都是正确的。它是生成事件的操作系统

由于这是一个游戏,它必须能够运行超过4个键在同一时间

package game;


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;

import game.sfx.Screen;
import game.sfx.SpriteSheet;

public class Game implements Runnable{


    private static final long serialVersionUID = 1L;

    public static final int WIDTH = 160;
    public static final int HEIGHT = WIDTH / 12 * 9;
    public static final int SCALE = 3;
    public static final String NAME = "Game";

    private JFrame frame;
    private JPanel panel;

    public boolean running = false;
    public int tickCount = 0;

    private BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
    private int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();

    Screen screen;

    public Game(){
        panel = new JPanel();

        panel.setMinimumSize(new Dimension(WIDTH*SCALE, HEIGHT*SCALE));
        panel.setMaximumSize(new Dimension(WIDTH*SCALE, HEIGHT*SCALE));
        panel.setPreferredSize(new Dimension(WIDTH*SCALE, HEIGHT*SCALE));

        frame = new JFrame(NAME);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());

        frame.add(panel, BorderLayout.CENTER);
        frame.pack();

        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true); 

        InputMap im = panel.getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW); // key binding here
        ActionMap am = panel.getActionMap();

        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "r");
        am.put("r", new InputHandler("right", this));
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "l");
        am.put("l", new InputHandler("left", this));    
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "u");
        am.put("u", new InputHandler("up", this));  
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "d");
        am.put("d", new InputHandler("down", this));    

    }


    public void init(){
        screen = new Screen(WIDTH, HEIGHT, new SpriteSheet("res/Untitled.png"));
    }

    public synchronized void start() {
        running = true;
        new Thread(this).start();
    }

    public synchronized void stop() {
        running = false;
    }

    public void run() {     
        long lastTime = System.nanoTime();
        double nsPerTick = 1000000000D/60D;

        int frames = 0;
        int ticks = 0;

        long lastTimer = System.currentTimeMillis();
        double delta = 0;

        init();

        while (running){
            long now = System.nanoTime();
            delta += (now - lastTime) / nsPerTick;
            lastTime = now;
            boolean shouldRender = true;
            while(delta >= 1)
            {
                ticks++;
                tick();
                delta -= 1;
                shouldRender = true;
            }

            try {
                Thread.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if (shouldRender)
            {
                frames++;
                render();
            }

            if(System.currentTimeMillis() - lastTimer >= 1000){
                lastTimer += 1000;
                System.out.println(ticks + " ticks, " + frames + " frames");
                frames = 0;
                ticks = 0;
            }
        }
    }

    public void tick(){
        tickCount++;


    }

    public void render(){


        screen.render(pixels, 0, WIDTH);

        Graphics g = panel.getGraphics();

        g.drawImage(image, 0, 0, panel.getWidth(), panel.getHeight(), null);

        g.dispose();

    }

    public static void main(String[] args){ 
        new Game().start();     
    }

}

class InputHandler extends AbstractAction {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private String key;
    private Game game;


    public InputHandler(String key, Game game) {
        this.key = key;
        this.game = game;
    }


    @Override
    public void actionPerformed(ActionEvent e) {        
        switch(key){
        case "right": 
        game.screen.xOffset+=2;
        break;
        case "left": 
        game.screen.xOffset-=2;
        break;
        case "up": 
        game.screen.yOffset+=2;
        break;
        case "down": 
        game.screen.yOffset-=2;
        break;
        }

    }

}
因此,解决方案是在按下/释放每个键时跟踪它


退房。
KeyboardAnimation
示例显示了如何使用键绑定来完成此操作。

相关代码在哪里?没有这个,你的问题就很难回答。请阅读链接,然后尝试创建并发布其中一个与您的问题相关的程序。这不是您的完整程序或链接,而是一个单独的可运行的小程序,它向我们演示了您的问题。您的相关代码在哪里可能重复?没有这个,你的问题就很难回答。请阅读链接,然后尝试创建并发布其中一个与您的问题相关的程序。这不是你的完整程序或链接,而是一个单独的可运行的小程序,它向我们展示了你的问题。当我运行代码时,当按下“向上/向下”和“左/右”时,正方形成功地沿对角线移动。然而,当我向上、向下和向左按时,为什么正方形不向左移动?向上/向下的方向不会取消,而直接向左走吗?这不是问题,我只是想理解。@Ilann:当我同时按下上/下/左键时,它会转到左边。@Ilann:我自己的代码,从链接到我以前的答案。好吧,我再试了一次。我不知道为什么会有不同。只要按下两个键,其他键就会失去反应。我看了你的答案。当我运行代码时,当按下“向上/向下”和“左/右”时,正方形成功地沿对角线移动。然而,当我向上、向下和向左按时,为什么正方形不向左移动?向上/向下的方向不会取消,而直接向左走吗?这不是问题,我只是想理解。@Ilann:当我同时按下上/下/左键时,它会转到左边。@Ilann:我自己的代码,从链接到我以前的答案。好吧,我再试了一次。我不知道为什么不一样。只要按下两个键,其他键就会失去反应。