简体   繁体   中英

How to rotate an ImageIcon() with actionPerformed()?

I am having difficulties rotating an imageicon by using the arrow keys.

I currently have the following as my code

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;

public class startGame extends JPanel implements ActionListener,KeyListener
{
Timer time = new Timer(5,this);
int x=0,y=0,velX = 0,velY=0;
Image car1;

public static void main(String[] args) 
{
    startGame game = new startGame();
    JFrame frame = new JFrame();
    frame.setTitle("NEED FOR SPEED");
    frame.setSize(800,800);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(game);
}

public void paintComponent(Graphics g)
{
    super.paintComponent(g);
    Graphics2D ga = (Graphics2D) g;
    ImageIcon ii = new ImageIcon("car1.jpg");
    car1=ii.getImage();
    ga.drawImage(car1, x, y, null);
    time.start();
}

public startGame()
{
    time.start();
    addKeyListener(this);
    setFocusable(true);
    setFocusTraversalKeysEnabled(false);
    repaint();
}

public void actionPerformed(ActionEvent e) 
{
    if(x<0)
    {
        velX=0;
        x=0;
    }
    if(y<0)
    {
        velY=0;
        y=0;
    }
    if(x>800)
    {
        velX=0;
        x=800;
    }
    if(y>800)
    {
        velY=0;
        y=800;
    }
    x = x + velX;
    y = y + velY;
    repaint();
}

public void keyTyped(KeyEvent e)
{
}

public void keyReleased(KeyEvent e)
{
    velX=0;
    velY=0;
}

public void keyPressed(KeyEvent e) 
{
    int c = e.getKeyCode();

    if(c == KeyEvent.VK_LEFT)
    {
        velX = -1;
        velY = 0;
    }
    if(c == KeyEvent.VK_UP)
    {
        velX = 0;
        velY = -1;
    }
    if(c == KeyEvent.VK_RIGHT)
    {
        velX = 1;
        velY = 0;
    }
    if(c == KeyEvent.VK_DOWN)
    {
        velX = 0;
        velY = 1;
    }
}
}

To rotate the image I have tried the following in the paint component method

ga.rotate(Math.toRadians(45),26,26);

and

ga.rotate(Math.toRadians(360));

but all it does is rotate the paint component and not the image.

What I am looking for is how can I rotate the image "car1" only, so that when VK_RIGHT OR VK_LEFT is pressed the image rotates to the desired direction, respectively. Also when VK_UP or VK_DOWN are pressed the image rotates to that direction, respectively.

And sorry for the lengthy code, but all was necessary. As the question involves multiple methods.

Thank you forum.

  • Please dont use KeyListener / KeyAdapter thats for AWT. Rather use KeyBinding s for Swing components (with no exceptions IMO).

  • Unless another class should have access to the KeyListener keyPressed etc methods (though you shouldn't use this) or actionPerformed than there is no need for the class to implement it, rather create an instance to work with within the class.

  • Also rather override getPreferredSize of JPanel so you can call pack() on JFrame rather than setSize() which is bad practice. Also never set JFrame visible before all components have been added

  • Also I see you start your timer in 2 places (the constructor and paintComponent ), rather just start it in the constructor and it will remain running unless you called Timer#setRepeats(false) .

  • I see no use for ImageIcon , rather just simply used a BufferedImage

  • Do not load images or do lenghty operations etc in paintComponent(..) besides pure drawing

As per above here is your code with fixes:

NB: I used my own KeyBinding class just to make things a bit easier.

在此处输入图片说明

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class Nfs {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame("Need for Speed");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new startGame());
                frame.pack();
                frame.setVisible(true);
            }
        });
    }
}

class startGame extends JPanel {

    private int x = 0, y = 0, velX = 0, velY = 0, width = 800, height = 600;
    private BufferedImage transformedImage;
    private Timer time = new Timer(5, new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            if (x < 0) {
                velX = 0;
                x = 0;
            }
            if (y < 0) {
                velY = 0;
                y = 0;
            }
            if (x > width) {
                velX = 0;
                x = width;
            }
            if (y > height) {
                velY = 0;
                y = height;
            }
            x = x + velX;
            y = y + velY;
            repaint();
        }
    });

    public startGame() {

        transformedImage = createTransformedImage(createCar(), 45);

        addKeyBindings();
        time.start();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D ga = (Graphics2D) g;

        ga.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        ga.drawImage(transformedImage, x, y, null);
    }
    //Simply used for testing (to simulate sprites) 

    public static BufferedImage createCar() {
        BufferedImage img = new BufferedImage(100, 100, BufferedImage.TRANSLUCENT);
        Graphics2D g2 = img.createGraphics();
        g2.setColor(Color.GREEN);
        g2.fillRect(0, 0, img.getWidth(), img.getHeight());
        g2.dispose();
        return img;
    }

    //https://stackoverflow.com/questions/4156518/rotate-an-image-in-java
    public static BufferedImage createTransformedImage(BufferedImage image, double angle) {
        double sin = Math.abs(Math.sin(angle)), cos = Math.abs(Math.cos(angle));
        int w = image.getWidth(), h = image.getHeight();
        int neww = (int) Math.floor(w * cos + h * sin), newh = (int) Math.floor(h * cos + w * sin);
        BufferedImage result = new BufferedImage(neww, newh, Transparency.TRANSLUCENT);
        Graphics2D g2d = result.createGraphics();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.translate((neww - w) / 2, (newh - h) / 2);
        g2d.rotate(angle, w / 2, h / 2);
        g2d.drawRenderedImage(image, null);
        g2d.dispose();
        return result;
    }

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

    private void addKeyBindings() {
        AbstractAction onReleaseAction = new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                velX = 0;
                velY = 0;
            }
        };

        //we are adding multiple keybindigs with same focus map etc to same component so we intitae an instance of class rate than use static methods
        KeyBinding kb = new KeyBinding(this, KeyBinding.WHEN_IN_FOCUSED_WINDOW);

        kb.addKeyBindingOnPressAndRelease(KeyEvent.VK_DOWN, new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                velX = 0;
                velY = 1;
            }
        }, "down pressed", onReleaseAction, "down released");

        kb.addKeyBindingOnPressAndRelease(KeyEvent.VK_UP, new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                velX = 0;
                velY = -1;
            }
        }, "up pressed", onReleaseAction, "up released");

        kb.addKeyBindingOnPressAndRelease(KeyEvent.VK_LEFT, new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                velX = -1;
                velY = 0;
            }
        }, "left pressed", onReleaseAction, "left released");
        kb.addKeyBindingOnPressAndRelease(KeyEvent.VK_RIGHT, new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                velX = 1;
                velY = 0;
            }
        }, "right pressed", onReleaseAction, "right released");
    }
}

class KeyBinding {

    private final JComponent container;
    private final int inputMap;
    public static final int WHEN_IN_FOCUSED_WINDOW = JComponent.WHEN_IN_FOCUSED_WINDOW,
            WHEN_FOCUSED = JComponent.WHEN_FOCUSED,
            WHEN_ANCESTOR_OF_FOCUSED_COMPONENT = JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT;

    public KeyBinding(JComponent container, int inputMap) {
        this.container = container;
        this.inputMap = inputMap;
    }

    public void addKeyBinding(int key, boolean onRelease, AbstractAction keybindingAction, String description) {
        putKeyBinding(container, inputMap, key, onRelease, keybindingAction, description);
    }

    public void addKeyBindingOnPress(int key, AbstractAction keybindingAction, String description) {
        putKeyBinding(container, inputMap, key, false, keybindingAction, description);
    }

    public void addKeyBindingOnRelease(int key, AbstractAction keybindingAction, String description) {
        putKeyBinding(container, inputMap, key, true, keybindingAction, description);
    }

    public void addKeyBindingOnPressAndRelease(int key, AbstractAction onPressAction, String onPressDesc, AbstractAction onReleaseAction, String onReleaseDesc) {
        putKeyBinding(container, inputMap, key, false, onPressAction, onPressDesc);
        putKeyBinding(container, inputMap, key, true, onReleaseAction, onReleaseDesc);
    }

    public static void putKeyBinding(JComponent container, int inputMap, int key, boolean onRelease, AbstractAction keybindingAction, String description) {
        container.getInputMap(inputMap).put(KeyStroke.getKeyStroke(key, 0, onRelease), description);
        container.getActionMap().put(description, keybindingAction);
    }

    public static void putKeyBindingOnPress(JComponent container, int inputMap, int key, AbstractAction keybindingAction, String description) {
        container.getInputMap(inputMap).put(KeyStroke.getKeyStroke(key, 0, false), description);
        container.getActionMap().put(description, keybindingAction);
    }

    public static void putKeyBindingOnRelease(JComponent container, int inputMap, int key, AbstractAction keybindingAction, String description) {
        container.getInputMap(inputMap).put(KeyStroke.getKeyStroke(key, 0, true), description);
        container.getActionMap().put(description, keybindingAction);
    }

    public static void putKeyBindingOnPressAndRelease(JComponent container, int inputMap, int key, AbstractAction onPressAction, String onPressDesc, AbstractAction onReleaseAction, String onReleaseDesc) {
        putKeyBinding(container, inputMap, key, false, onPressAction, onPressDesc);
        putKeyBinding(container, inputMap, key, true, onReleaseAction, onReleaseDesc);
    }
}

References:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM