移动缓冲图像特定坐标 [英] moving buffered image to specific coordinates

查看:229
本文介绍了移动缓冲图像特定坐标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过pressing箭头键移动网格周围的蓝色方形。我已经设置了的KeyListener 但是当我重画框架,我要为了它更新四处移动框。我如何使它成为一个流畅的动画效果(移动从一个正方形的坐标到另一个)?

例如:

 如果(键code == KeyEvent.VK_LEFT){
    X5 = X5-的xChange;
    frame.repaint();
}

我的图片被缓冲的图像和均设置为特定坐标。
这里是我的图形类:

 公共静态类myGraphicsPanel继承JPanel {
    公共无效的paintComponent(图形G){
      super.paintComponent方法(G);
      g.drawImage(块1,X1,Y1,空);
      g.drawImage(块2,X2,Y2,空);
      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(蓝色,X9,Y9,NULL);
}


解决方案

您的问题是缺乏大量的信息,如何屏幕更新?屏幕是如何创建的?你的对象有什么关系,彼此?

许多这些问题可以用一个 MCVE

回答

动画是随时间变化的错觉。所以,你需要一些东西。你需要一些方法来改变目前的状态和某种方式来触发并随着时间的推移更新到用户界面。

要摆在最简单的(和最安全)的方法是使用一个Swing 定时

动画

 进口java.awt.Dimension中;
进口java.awt.EventQueue中;
进口java.awt.Graphics;
进口java.awt.Graphics2D中;
进口java.awt.event.ActionEvent中;
进口java.awt.event.ActionListener;
进口java.awt.image.BufferedImage中;
进口的java.io.File;
进口java.io.IOException异常;
进口了java.util.Random;
进口java.util.logging.Level中;
进口java.util.logging.Logger中;
进口javax.imageio.ImageIO中;
进口javax.swing.JFrame中;
进口javax.swing.JPanel中;
进口javax.swing.UIManager中;
进口javax.swing.UnsupportedLookAndFeelException;
进口javax.swing.Timer中;公共类TestAnimation {    公共静态无效的主要(字串[] args){
        新TestAnimation();
    }    公共TestAnimation(){
        EventQueue.invokeLater(新的Runnable(){
            @覆盖
            公共无效的run(){
                尝试{
                    尝试{
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    }赶上(ClassNotFoundException的| InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException前){
                        ex.printStackTrace();
                    }                    JFrame的帧=新的JFrame(测试);
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(新TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(NULL);
                    frame.setVisible(真);
                }赶上(IOException异常前){
                    ex.printStackTrace();
                }
            }
        });
    }    公共类TestPane继承JPanel {        私人的BufferedImage IMG;        私人诠释xDelta,yDelta;
        私人诠释XPOS,yPos;        公共TestPane()抛出IOException
            IMG = ImageIO.read(新文件(/用户/巴蒂尔/ Dropbox的/ MegaTokyo / thumnails / 2.JPG));
            随机RND =新的随机();
            做{
                xDelta = rnd.nextInt(4);
            }而(xDelta == 0);
            做{
                yDelta = rnd.nextInt(4);
            }而(yDelta == 0);
            如果(rnd.nextBoolean()){
                xDelta * = -1;
            }
            如果(rnd.nextBoolean()){
                yDelta * = -1;
            }            (GET preferredSize()宽度 - img.getWidth())= XPOS / 2;
            yPos =(GET preferredSize()高度 - img.getHeight())/ 2;            定时器定时器=新定时器(40,新的ActionListener(){
                @覆盖
                公共无效的actionPerformed(ActionEvent的五){
                    XPOS + = xDelta;
                    yPos + = yDelta;
                    如果(XPOS + img.getWidth()>的getWidth()){
                        XPOS =的getWidth() - img.getWidth();
                        xDelta * = -1;
                    }否则如果(XPOS℃,){
                        XPOS = 0;
                        xDelta * = -1;
                    }
                    如果(yPos + img.getHeight()>的getHeight()){
                        yPos =的getHeight() - img.getHeight();
                        yDelta * = -1;
                    }否则如果(yPos℃,){
                        yPos = 0;
                        yDelta * = -1;
                    }                    重绘();
                }
            });
            timer.start();
        }        @覆盖
        公共尺寸的get preferredSize(){
            返回新尺寸(400,400);
        }        @覆盖
        保护无效paintComponent(图形G){
            super.paintComponent方法(G);
            如果(IMG!= NULL){
                Graphics2D的G2D =(Graphics2D的)g.create();
                g2d.drawImage(IMG,XPOS,yPos,这一点);
                g2d.dispose();
            }
        }    }}

在有并发在Swing 定睛一看,的 w将使用Swing定时器的更多细节。

但是,你怎么做到这一点使用的键盘?出人意料的是,这是非常相似的。

 进口java.awt.Dimension中;
进口java.awt.EventQueue中;
进口java.awt.Graphics;
进口java.awt.Graphics2D中;
进口java.awt.event.ActionEvent中;
进口java.awt.event.KeyEvent中;
进口java.awt.image.BufferedImage中;
进口的java.io.File;
进口java.io.IOException异常;
进口javax.imageio.ImageIO中;
进口javax.swing.AbstractAction中;
进口javax.swing.Action中;
进口javax.swing.ActionMap中;
进口javax.swing.InputMap中;
进口javax.swing.JFrame中;
进口javax.swing.JPanel中;
进口javax.swing.KeyStroke;
进口javax.swing.UIManager中;
进口javax.swing.UnsupportedLookAndFeelException;公共类TestAnimation {    公共静态无效的主要(字串[] args){
        新TestAnimation();
    }    公共TestAnimation(){
        EventQueue.invokeLater(新的Runnable(){
            @覆盖
            公共无效的run(){
                尝试{
                    尝试{
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    }赶上(ClassNotFoundException的| InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException前){
                        ex.printStackTrace();
                    }                    JFrame的帧=新的JFrame(测试);
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(新TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(NULL);
                    frame.setVisible(真);
                }赶上(IOException异常前){
                    ex.printStackTrace();
                }
            }
        });
    }    公共类TestPane继承JPanel {        私人的BufferedImage IMG;
        私人诠释XPOS,yPos;        公共TestPane()抛出IOException
            IMG = ImageIO.read(新文件(/用户/巴蒂尔/ Dropbox的/ MegaTokyo / thumnails / 2.JPG));            (GET preferredSize()宽度 - img.getWidth())= XPOS / 2;
            yPos =(GET preferredSize()高度 - img.getHeight())/ 2;            addKeyBinding(上,KeyStroke.getKeyStroke(KeyEvent.VK_UP,0),新KeyAction(0,-4));
            addKeyBinding(向下,KeyStroke.getKeyStroke(KeyEvent.VK_DOWN,0),新KeyAction(0,4));
            addKeyBinding(左,KeyStroke.getKeyStroke(KeyEvent.VK_LEFT,0),新KeyAction(-4,0));
            addKeyBinding(右,KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,0),新KeyAction(4,0));
        }        保护无效addKeyBinding(字符串名称,按键击键动作动作){
            IM的InputMap = getInputMap中(WHEN_IN_FOCUSED_WINDOW);
            ActionMap中上午= getActionMap();            im.put(击键名);
            am.put(名称,动作);
        }        @覆盖
        公共尺寸的get preferredSize(){
            返回新尺寸(400,400);
        }        @覆盖
        保护无效paintComponent(图形G){
            super.paintComponent方法(G);
            如果(IMG!= NULL){
                Graphics2D的G2D =(Graphics2D的)g.create();
                g2d.drawImage(IMG,XPOS,yPos,这一点);
                g2d.dispose();
            }
        }        公共类KeyAction扩展AbstractAction {            私人诠释xDelta,yDelta;            公共KeyAction(INT xDelta,诠释yDelta){
                this.xDelta = xDelta;
                this.yDelta = yDelta;
            }            @覆盖
            公共无效的actionPerformed(ActionEvent的五){
                XPOS + = xDelta;
                yPos + = yDelta;
                如果(XPOS + img.getWidth()>的getWidth()){
                    XPOS =的getWidth() - img.getWidth();
                }否则如果(XPOS℃,){
                    XPOS = 0;
                }
                如果(yPos + img.getHeight()>的getHeight()){
                    yPos =的getHeight() - img.getHeight();
                }否则如果(yPos℃,){
                    yPos = 0;
                }                重绘();
            }        }    }}

看一看如何使用键绑定如何使用行动的更多细节。

I am trying to move the blue square around the grid by pressing the arrow keys. I already set up the KeyListener but when I repaint the frame, I have to move the frame around in order for it to update. How do I make it a smooth animation (moving the square from one coordinate to another)?

Example:

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

My images are buffered images and are all set to specific coordinates. Here is my graphics 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);
}

解决方案

You question is lacking a lot of information, how is the screen updated? How is the screen created? What relationship do the objects have with each other?

Many of these questions could be answered with a MCVE

Animation is the illusion of change over time. So you need a few things. You need some way to change the current state and some way to trigger and update to the UI over time.

The simplest (and safest) way to do this within Swing is to use a 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();
            }
        }

    }

}

Have a closer look at Concurrency in Swing and w to Use Swing Timers for more details

But, how do you do this using the key board? Surprisingly, it's very similar.

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();
            }

        }

    }

}

Have a look at How to use key bindings and How to use actions for more details

这篇关于移动缓冲图像特定坐标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆