when using a global variable isn't really global - using buttons to rotate a drawing

HI,

I've now added some actions to buttons that I have within a Java2D program. I want to be able to use these buttons to rotate a drawing within a panel by 45 degrees right and left. I've written the code to rotate the drawing as follows,

AffineTransform at = new AffineTransform();
at.translate(size/2.0, size/2.0); //third transform
at.rotate(Math.toRadians(45)); //second transform
at.translate(-size/2.0, -size/2.0); //first transform

This allows the drawing to be rotated by 45 degrees. My question is how do I link this rotation to the buttons so they will rotate the drawing I've already got in the panel.

My current code is as follows,

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

public class PacMan2Clicks extends JFrame implements ActionListener,
        MouseMotionListener, MouseListener {
   
    public static int mode = 0;
    private static JButton rightButton;
    private static JButton leftButton;
    private Image pacmanImage;
    private int pacmanX, pacmanY;
    JPanel panel = new JPanel();
   
    public PacMan2Clicks() {
       
        Container contentPane = getContentPane();
       
        JPanel panel = new JPanel() {
            public void paintComponent(Graphics g) {
                super.paintComponent(g);
                setPacMan(g);
            }
        };
       
        panel.addMouseMotionListener(this);
        panel.addMouseListener(this);
        JPanel buttonPanel = new JPanel();
        panel.setBackground(Color.WHITE);
        leftButton = new JButton("Left");
        leftButton.addActionListener(this);
        buttonPanel.add(leftButton);
       
        rightButton = new JButton("Right");
        rightButton.addActionListener(this);
        buttonPanel.add(rightButton);
       
        contentPane.add(panel, BorderLayout.CENTER);
        contentPane.add(buttonPanel, BorderLayout.SOUTH);
    }
   
    private void setPacMan(Graphics g) {
        Dimension d = getSize();
        int size = 100;
        Ellipse2D.Double head = new Ellipse2D.Double(0, 0, size, size);
        Ellipse2D.Double eye = new Ellipse2D.Double(size / 2 - 1, size / 5 - 1,
                size / 10, size / 10);
        GeneralPath mouth = new GeneralPath();
        mouth.moveTo(size, size / 4);
        mouth.lineTo(size / 8, size / 2);
        mouth.lineTo(size, size * 3 / 4);
        mouth.closePath();
       
        Area pacman = new Area(head);
        pacman.subtract(new Area(eye));
        pacman.subtract(new Area(mouth));
       
        Graphics2D g2 = (Graphics2D) g;
        g2.translate(pacmanX, pacmanY);
        g2.setPaint(Color.yellow);
        g2.fill(pacman);
        g2.draw(pacman);
    }
   
    protected void clearDisplay() {
       
    }
   
    public void mouseDragged(MouseEvent e) {
       
        pacmanX = e.getX();
        pacmanY = e.getY();
        repaint();
    }
   
    public void mouseReleased(MouseEvent e) {}
    public void mouseMoved(MouseEvent e){}
    public void mouseClicked(MouseEvent e){
        JPanel panel = new JPanel();
        if (e.getClickCount() == 2) {
            pacmanX = e.getX();
            pacmanY = e.getY();
            repaint();
        }
    }
    public void mouseExited(MouseEvent e){}
    public void mouseEntered(MouseEvent e){}
    public void mousePressed(MouseEvent e) {}
   
    public void actionPerformed(ActionEvent event) {
        if (event.getSource().equals(rightButton)) {
           
           
        } else if (event.getSource().equals(leftButton)) {
           
        }
    }
   
    public static void main(String[] args) {
       
        PacMan2Clicks frame = new PacMan2Clicks();
        frame.setSize(600, 600);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

Any help really appreciated.

Thanks
nhay59Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

nhay59Author Commented:
Hi,

Sorry, I should have said. I know this code needs to go in the actionPerformed() method, with a positive 45 to go right and a -45 to go left. The problem is I'm not sure how to link this to the actual drawing within the panel.

Thanks
CEHJCommented:
Just set an instance variable to an angle of rotation. You can then apply that to the transform
    public void actionPerformed(ActionEvent event) {
        if (event.getSource().equals(rightButton)) {
              angleOfRotation += Math.toRadians(5);
           
        } else if (event.getSource().equals(leftButton)) {
          angleOfRotation -= Math.toRadians(5);
        }
        repaint();
    }

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
nhay59Author Commented:
Hi,

Thanks for the reply. I've tried implementing your recommendations, and to no avail so far. When I press the appropriate button on the panel, nothing happens to the PacMan drawing. I know the AffineTransform method works, because I've tried it within the actual drawing of the PacMan, but it won't work with the buttons.

Any help or advice appreciated.

Thanks
Exploring ASP.NET Core: Fundamentals

Learn to build web apps and services, IoT apps, and mobile backends by covering the fundamentals of ASP.NET Core and  exploring the core foundations for app libraries.

CEHJCommented:
How are you applying 'angleOfRotation' to the transform?
nhay59Author Commented:
Hi,

I've changed the code as follows, but I get an error with the transform call in the setPacMan method. I think I must be applying your advice incorrectly. I need to be able to link the actual drawing of the PacMan object to the methods so I can also delete PacMan when a user double clicks on it, and select the PacMan with one click etc.

Code so far is as follows,

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

public class PacMan2Clicks extends JFrame implements ActionListener,
        MouseMotionListener, MouseListener {
   
    public static int mode = 0;
    private static JButton rightButton;
    private static JButton leftButton;
    private Image pacmanImage;
    private int pacmanX, pacmanY;
    JPanel panel = new JPanel();
    int angleOfRotation;
   
    public PacMan2Clicks() {
       
        Container contentPane = getContentPane();
       
        JPanel panel = new JPanel() {
            public void paintComponent(Graphics g) {
                super.paintComponent(g);
                setPacMan(g);
            }
        };
       
        panel.addMouseMotionListener(this);
        panel.addMouseListener(this);
        JPanel buttonPanel = new JPanel();
        panel.setBackground(Color.WHITE);
        leftButton = new JButton("Left");
        leftButton.addActionListener(this);
        buttonPanel.add(leftButton);
       
        rightButton = new JButton("Right");
        rightButton.addActionListener(this);
        buttonPanel.add(rightButton);
       
        contentPane.add(panel, BorderLayout.CENTER);
        contentPane.add(buttonPanel, BorderLayout.SOUTH);
    }
   
    private void setPacMan(Graphics g) {
        Dimension d = getSize();
        int size = 100;
        Ellipse2D.Double head = new Ellipse2D.Double(0, 0, size, size);
        Ellipse2D.Double eye = new Ellipse2D.Double(size / 2 - 1, size / 5 - 1,
                size / 10, size / 10);
        GeneralPath mouth = new GeneralPath();
        mouth.moveTo(size, size / 4);
        mouth.lineTo(size / 8, size / 2);
        mouth.lineTo(size, size * 3 / 4);
        mouth.closePath();
       
        Area pacman = new Area(head);
        pacman.subtract(new Area(eye));
        pacman.subtract(new Area(mouth));
       
        Graphics2D g2 = (Graphics2D) g;
        g2.translate(pacmanX, pacmanY);
        g2.setTransform(angleOfRotation);
        g2.setPaint(Color.yellow);
        g2.fill(pacman);
        g2.draw(pacman);
    }
   
    protected void clearDisplay() {
       
    }
   
    public void mouseDragged(MouseEvent e) {
       
        pacmanX = e.getX();
        pacmanY = e.getY();
        repaint();
    }
   
    public void mouseReleased(MouseEvent e) {}
    public void mouseMoved(MouseEvent e){}
    public void mouseClicked(MouseEvent e){
        JPanel panel = new JPanel();
        if (e.getClickCount() == 2) {
            pacmanX = e.getX();
            pacmanY = e.getY();
            repaint();
        }
    }
    public void mouseExited(MouseEvent e){}
    public void mouseEntered(MouseEvent e){}
    public void mousePressed(MouseEvent e) {}
   
    public void actionPerformed(ActionEvent event) {
       
        if (event.getSource().equals(rightButton)) {
            angleOfRotation += Math.toRadians(5);
           
        } else if (event.getSource().equals(leftButton)) {
            angleOfRotation -= Math.toRadians(5);
        }
    }
   
    public static void main(String[] args) {
       
        PacMan2Clicks frame = new PacMan2Clicks();
        frame.setSize(600, 600);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

I do apologise if this is not what you meant. I've tried to apply it as I understand it.

Thanks for your help.
CEHJCommented:
>>g2.setTransform(angleOfRotation); //wrong


g2.rotate(angleOfRotation); // right
CEHJCommented:
angleOfRotation should also be a double
Mick BarryJava DeveloperCommented:
>     if (event.getSource().equals(rightButton)) {

that only needs to be:

    if (event.getSource()==rightButton) {

>       } else if (event.getSource().equals(leftButton)) {

same here

nhay59Author Commented:
Hi,

Thank you both for your replies. I'm happy to say that the PacMan is now rotating both ways. However, as you might expect with my programs, there is a small problem.

The problem is as follows. When a user presses the left or right button, the PacMan is rotated but not in real time (ie: you don't actually see the PacMan figure rotating on the screen.) The only way to actually see that the PacMan has been rotated is to either drag it or double click to create a new one.

Why would the PacMan not actually rotate as you click the buttons? Why is it necessary to eith drag or creat a new PacMan?

Help always appreciated.

Thanks
Mick BarryJava DeveloperCommented:
try adding a call to repaint() after you have changed the angle.
nhay59Author Commented:
Hi,

Thanks for the help. It works exactly as required now. It's actually quite fun to play with for a while.

Have a great weekend.
CEHJCommented:
:-)
Mick BarryJava DeveloperCommented:
no worries :)
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.