将缓冲图像移动到特定坐标

moving buffered image to specific coordinates

我正在尝试通过按箭头键在网格周围移动蓝色方块。我已经设置了 KeyListener 但是当我重新绘制框架时,我必须移动框架以使其更新。如何让它成为一个流畅的动画(将正方形从一个坐标移动到另一个坐标)?

示例:

if (keyCode == KeyEvent.VK_LEFT){
    x5=x5-xChange;
    frame.repaint();
}

我的图像是缓冲图像,并且都设置为特定坐标。 这是我的图形 class:

public static class myGraphicsPanel extends JPanel {   
    public void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      g.drawImage(block1,x1,y1,null);
      g.drawImage(block2,x2,y2,null);
      g.drawImage(block3,x3,y3,null);
      g.drawImage(block4,x4,y4,null);
      g.drawImage(block5,x5,y5,null);
      g.drawImage(block6,x6,y6,null);
      g.drawImage(block7,x7,y7,null);
      g.drawImage(block8,x8,y8,null);
      g.drawImage(blue,x9,y9,null);
}

尽量不要重绘整个面板,而只重绘要绘制正方形的区域,使用

repaint(int x, int y , int width , int height);

其中 x 和 y 是坐标,宽度和高度是正方形的宽度和高度。

您可以为每个 BufferedImage 指定一个目标变量。您将检查当前 x 位置是否大于或小于目标变量,并根据值进行更改。您也可以使用 y 坐标来执行此操作。

int x1 = 100;
int x2 = 100;
int xTarget1 = 200; // x target coordinate
int xTarget2 = 200;
// And so on, for as many BufferedImages

int xChange = 1;

// A loop, wherever it may be.
public void loop() {

    if(x1 > xTarget1) {
        x1 = x1 - xChange;
    else if(x1 < xTarget1) {
        x1 = x1 + xChange;
    }
    // Same for the other BufferedImages

}

然后你会画出来。这应该使您的图像移动更加流畅。除非您通过更改更改速度变量,否则它将是一个恒定的移动。希望对您有所帮助。

你的问题缺少很多信息,屏幕是如何更新的?屏幕是如何创建的?对象之间有什么关系?

其中许多问题都可以用 MCVE

来回答

动画是随时间变化的幻觉。所以你需要一些东西。您需要一些方法来更改当前状态以及一些方法来随着时间的推移触发和更新 UI。

在 Swing 中执行此操作的最简单(也是最安全)的方法是使用 Swing Timer

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.Timer;

public class TestAnimation {

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

    public TestAnimation() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }

                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage img;

        private int xDelta, yDelta;
        private int xPos, yPos;

        public TestPane() throws IOException {
            img = ImageIO.read(new File("/Users/shane/Dropbox/MegaTokyo/thumnails/2.jpg"));
            Random rnd = new Random();
            do {
                xDelta = rnd.nextInt(4);
            } while (xDelta == 0);
            do {
                yDelta = rnd.nextInt(4);
            } while (yDelta == 0);
            if (rnd.nextBoolean()) {
                xDelta *= -1;
            }
            if (rnd.nextBoolean()) {
                yDelta *= -1;
            }

            xPos = (getPreferredSize().width - img.getWidth()) / 2;
            yPos = (getPreferredSize().height - img.getHeight()) / 2;

            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    xPos += xDelta;
                    yPos += yDelta;
                    if (xPos + img.getWidth() > getWidth()) { 
                        xPos = getWidth() - img.getWidth();
                        xDelta *= -1;
                    } else if (xPos < 0) {
                        xPos = 0;
                        xDelta *= -1;
                    }
                    if (yPos + img.getHeight() > getHeight()) { 
                        yPos = getHeight() - img.getHeight();
                        yDelta *= -1;
                    } else if (yPos < 0) {
                        yPos = 0;
                        yDelta *= -1;
                    }

                    repaint();
                }
            });
            timer.start();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (img != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.drawImage(img, xPos, yPos, this);
                g2d.dispose();
            }
        }

    }

}

仔细查看 Concurrency in Swing and w to Use Swing Timers 了解更多详情

但是,如何使用键盘执行此操作?令人惊讶的是,它非常相似。

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestAnimation {

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

    public TestAnimation() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }

                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage img;
        private int xPos, yPos;

        public TestPane() throws IOException {
            img = ImageIO.read(new File("/Users/shane/Dropbox/MegaTokyo/thumnails/2.jpg"));

            xPos = (getPreferredSize().width - img.getWidth()) / 2;
            yPos = (getPreferredSize().height - img.getHeight()) / 2;

            addKeyBinding("up", KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), new KeyAction(0, -4));
            addKeyBinding("down", KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), new KeyAction(0, 4));
            addKeyBinding("left", KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), new KeyAction(-4, 0));
            addKeyBinding("right", KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), new KeyAction(4, 0));
        }

        protected void addKeyBinding(String name, KeyStroke keyStroke, Action action) {
            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            ActionMap am = getActionMap();

            im.put(keyStroke, name);
            am.put(name, action);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (img != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.drawImage(img, xPos, yPos, this);
                g2d.dispose();
            }
        }

        public class KeyAction extends AbstractAction {

            private int xDelta, yDelta;

            public KeyAction(int xDelta, int yDelta) {
                this.xDelta = xDelta;
                this.yDelta = yDelta;
            }

            @Override
            public void actionPerformed(ActionEvent e) {
                xPos += xDelta;
                yPos += yDelta;
                if (xPos + img.getWidth() > getWidth()) {
                    xPos = getWidth() - img.getWidth();
                } else if (xPos < 0) {
                    xPos = 0;
                }
                if (yPos + img.getHeight() > getHeight()) {
                    yPos = getHeight() - img.getHeight();
                } else if (yPos < 0) {
                    yPos = 0;
                }

                repaint();
            }

        }

    }

}

查看 How to use key bindings and How to use actions 了解更多详情