java - 使用 keyBindings 移动 bufferedImage

标签 java swing animation bufferedimage key-bindings

我已经问了几个问题,但还没有取得任何突破。所以我按照这里的例子:http://www.camick.com/java/source/KeyboardAnimation.java那是指给我的。我为我的动画测试切换了 JLabel,它扩展了 JComponent。但是我仍然没有得到任何结果。我认为可能是动画类中的代码阻止了坐标的更新。这个类会干扰键绑定(bind)动画吗?(下面的这个类循环遍历行走动画的一些缓冲图像,而不是将其移动到屏幕上,而只是在一张静止图像和另一张静止图像之间切换,同时角色的腿部移动。)

import java.awt.Graphics;
import java.awt.image.BufferedImage;

import javax.swing.JComponent;



public class Animation extends JComponent{
    private static final long serialVersionUID = 1L;
    public BufferedImage currentFrame;
    public boolean walking=false;
    public int x=50;
    public int y=50;
    public int dx,dy;
    public void update()
    {
        if (walking){
            for(int frame=0;frame<(Art.player.length+1);frame++)
            {
                try{
                    currentFrame=Art.player[frame][0];
                    try {
                        Thread.sleep(200);
                        repaint();
                    } catch (InterruptedException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }           
                }catch(IndexOutOfBoundsException e)
                {
                    frame=0;
                    currentFrame=Art.player[frame][0];
                    try {
                        Thread.sleep(200);
                        repaint();
                    } catch (InterruptedException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }

                }
            }
        }else
        {
            currentFrame=Art.player[0][0];
        }
    }
    public void startAnimation()
    {
        walking=true;
    }
    public void stopAnimation()
    {
        walking=false;
    }
    public void paintComponent(Graphics g)
    {
        g.drawImage(currentFrame,x,y,null);
    }

}

这是键绑定(bind)类:

import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.util.Map;
import java.util.HashMap;
import javax.swing.*;

public class KeyboardAnimation implements ActionListener
{
    private final static String PRESSED = "pressed ";
    private final static String RELEASED = "released ";

    private JComponent component;
    private Timer timer;
    private Map<String, Point> pressedKeys = new HashMap<String, Point>();

    public KeyboardAnimation(JComponent component, int delay)
    {
        this.component = component;

        timer = new Timer(delay, this);
        timer.setInitialDelay( 0 );
    }

    /*
    *  &param keyStroke - see KeyStroke.getKeyStroke(String) for the format of
    *                     of the String. Except the "pressed|released" keywords
    *                     are not to be included in the string.
    */
    public void addAction(String keyStroke, int deltaX, int deltaY)
    {
        //  Separate the key identifier from the modifiers of the KeyStroke

        int offset = keyStroke.lastIndexOf(" ");
        String key = offset == -1 ? keyStroke :  keyStroke.substring( offset + 1 );
        String modifiers = keyStroke.replace(key, "");

        //  Get the InputMap and ActionMap of the component

        InputMap inputMap = component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
        ActionMap actionMap = component.getActionMap();

        //  Create Action and add binding for the pressed key

        Action pressedAction = new AnimationAction(key, new Point(deltaX, deltaY));
        String pressedKey = modifiers + PRESSED + key;
        KeyStroke pressedKeyStroke = KeyStroke.getKeyStroke(pressedKey);
        inputMap.put(pressedKeyStroke, pressedKey);
        actionMap.put(pressedKey, pressedAction);

        //  Create Action and add binding for the released key

        Action releasedAction = new AnimationAction(key, null);
        String releasedKey = modifiers + RELEASED + key;
        KeyStroke releasedKeyStroke = KeyStroke.getKeyStroke(releasedKey);
        inputMap.put(releasedKeyStroke, releasedKey);
        actionMap.put(releasedKey, releasedAction);
    }

    //  Invoked whenever a key is pressed or released

    private void handleKeyEvent(String key, Point moveDelta)
    {
        //  Keep track of which keys are pressed

        if (moveDelta == null)
            pressedKeys.remove( key );
        else
            pressedKeys.put(key, moveDelta);

        //  Start the Timer when the first key is pressed

        if (pressedKeys.size() == 1)
        {
            timer.start();
        }

        //  Stop the Timer when all keys have been released

        if (pressedKeys.size() == 0)
        {
            timer.stop();
        }
    }

    //  Invoked when the Timer fires

    public void actionPerformed(ActionEvent e)
    {
        moveComponent();
    }

    //  Move the component to its new location

    private void moveComponent()
    {
        int componentWidth = component.getSize().width;
        int componentHeight = component.getSize().height;

        Dimension parentSize = component.getParent().getSize();
        int parentWidth  = parentSize.width;
        int parentHeight = parentSize.height;

        //  Calculate new move

        int deltaX = 0;
        int deltaY = 0;

        for (Point delta : pressedKeys.values())
        {
            deltaX += delta.x;
            deltaY += delta.y;
        }


        //  Determine next X position

        int nextX = Math.max(component.getLocation().x + deltaX, 0);

        if ( nextX + componentWidth > parentWidth)
        {
            nextX = parentWidth - componentWidth;
        }

        //  Determine next Y position

        int nextY = Math.max(component.getLocation().y + deltaY, 0);

        if ( nextY + componentHeight > parentHeight)
        {
            nextY = parentHeight - componentHeight;
        }

        //  Move the component

        component.setLocation(nextX, nextY);
    }

    //  Action to keep track of the key and a Point to represent the movement
    //  of the component. A null Point is specified when the key is released.

    private class AnimationAction extends AbstractAction implements ActionListener
    {
        private Point moveDelta;

        public AnimationAction(String key, Point moveDelta)
        {
            super(key);

            this.moveDelta = moveDelta;
        }

        public void actionPerformed(ActionEvent e)
        {
            handleKeyEvent((String)getValue(NAME), moveDelta);
        }
    }

    public static void main(String[] args)
    {
        Animation test = new Animation();

        KeyboardAnimation animation = new KeyboardAnimation(test, 24);
        animation.addAction("LEFT", -3,  0);
        animation.addAction("RIGHT", 3,  0);
        animation.addAction("UP",    0, -3);
        animation.addAction("DOWN",  0,  3);

        animation.addAction("control LEFT", -5,  0);
        animation.addAction("V",  5,  5);

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.getContentPane().add(test);
        frame.setSize(600, 600);
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
        test.startAnimation();
        test.update();
    }

    static class ColorIcon implements Icon
    {
        private Color color;
        private int width;
        private int height;

        public ColorIcon(Color color, int width, int height)
        {
            this.color = color;
            this.width = width;
            this.height = height;
        }

        public int getIconWidth()
        {
            return width;
        }

        public int getIconHeight()
        {
            return height;
        }

        public void paintIcon(Component c, Graphics g, int x, int y)
        {
            g.setColor(color);
            g.fillRect(x, y, width, height);
        }
    }
}

最佳答案

Thread.sleep(200);
repaint();

不要阻塞 EDT(事件调度线程)——发生这种情况时 GUI 将“卡住”。不是调用 Thread.sleep(n) 而是实现 Swing 计时器来重复任务。请参阅Concurrency in Swing了解更多详情。

关于java - 使用 keyBindings 移动 bufferedImage,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17885529/

相关文章:

java - 在具有不断重新绘制的 JPanel 的 JApplet 中使用组件

ios - 动画 ios 应用程序中的黑色过渡

css - 展开带有动画的左侧 div 导致 "shakeness"

java - 如何跨 Eclipse 中的不同项目在 Android 中将字符串和整数从一个 Activity 传递到另一个 Activity ?

java - 如何在Java中单击JLabel时更改JLabel背景

java - Play Framework : redirect to a different domain

java - 如何在java桌面应用程序中设置 Crystal 报表参数

html - 在纯 css 图片上向下滑动

java - 从嵌入式 Glassfish 3.1 获取上下文

java - 通过启用另一个按钮来禁用一个按钮,反之亦然