using mouseDragged() to move an existing drawing in a Java2D program

HI,

I'm currently working my way through a Java2D program, and need to be able to drag an existing drawing to a new position with the mouse. When I try to run this program i get the following error,

Exception in thread "main" java.lang.StackOverflowError

This seems to specifically refer to the line 'PacMan_clickstest pacman = new PacMan_clickstest();' which is called on line 15. Does anybody know why this happening, and how can I correct this error, so I can drag the drawing around the window as required.

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.util.*;

public class PacMan_clickstest extends JPanel implements MouseListener, MouseMotionListener{
   
    public static int mode = 0;
    private static JButton rightButton;
    private static JButton leftButton;
    int last_x, last_y;
    boolean pressOut = false;
    PacMan_clickstest pacman = new PacMan_clickstest();
   
    public PacMan_clickstest(){
       
        addMouseListener(this);
        addMouseMotionListener(this);
       
    }
   
    public void mousePressed(MouseEvent e) {
        //PacMan_clickstest pacman = new PacMan_clickstest();
       
        last_x = e.getX();
        last_y = e.getY();
        pressOut = pacman.contains(e.getX(), e.getY());
    }
   
    public void mouseDragged(MouseEvent e){
        if ( !pressOut)
            updateLocation(e);
        //repaint();
    }
   
    public void mouseReleased(MouseEvent e) {}
    public void mouseMoved(MouseEvent e){}
    public void mouseClicked(MouseEvent e){}
    public void mouseExited(MouseEvent e){}
    public void mouseEntered(MouseEvent e){}
   
    public void updateLocation(MouseEvent e) {
        //PacMan_clickstest pacman = new PacMan_clickstest();
       
        pacman.setLocation(e.getX() - last_x, e.getY() - last_y);
        last_x = e.getX();
        last_y = e.getY();
       
        repaint();
    }
   
    public void paintComponent(Graphics g) {
        Dimension d = getSize();
       
        Graphics2D g2 = (Graphics2D)g;
       
        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));
        g2.setPaint(Color.yellow);
        g2.fill(pacman);
        g2.setPaint(Color.black);
        g2.draw(pacman);
    }
   
    public static void main(String[] args) {
        JFrame frame = new JFrame("Drawing stuff");
        Container contentPane = frame.getContentPane();
       
        JPanel panel = new JPanel();
        PacMan_clickstest pacman = new PacMan_clickstest();
       
        leftButton = new JButton("Left");
        //leftButton.addActionListener(pacman);
        panel.add(leftButton);
       
        rightButton = new JButton("Right");
        //rightButton.addActionListener(pacman);
        panel.add(rightButton);
       
        contentPane.add(panel, BorderLayout.SOUTH);
        contentPane.add(pacman, BorderLayout.CENTER);
       
        frame.setSize(600, 600);
        frame.setVisible(true);
       
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
    }
}

Any help or advice is 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.

zzynxSr. Software engineerCommented:
a stack overflow on such kind of a line... Must be something with recursivity
CEHJCommented:
You need in paintComponent to draw the image in its current position. You code has not significantly changed from the previous code in terms of its position
CEHJCommented:
>>//PacMan_clickstest pacman = new PacMan_clickstest();

Is not required. Just reset the position
Fundamentals of JavaScript

Learn the fundamentals of the popular programming language JavaScript so that you can explore the realm of web development.

zzynxSr. Software engineerCommented:
Oooo, of course!
Why do you have

>>   PacMan_clickstest pacman = new PacMan_clickstest();

that line?
zzynxSr. Software engineerCommented:
You call the constructor in the constructor in the constructor ....
zzynxSr. Software engineerCommented:
So, remove that line:

public class PacMan_clickstest extends JPanel implements MouseListener, MouseMotionListener{
   
    public static int mode = 0;
    private static JButton rightButton;
    private static JButton leftButton;
    int last_x, last_y;
    boolean pressOut = false;
    PacMan_clickstest pacman = new PacMan_clickstest();          // <<<<<<<<< this one
   
    public PacMan_clickstest(){
nhay59Author Commented:
Hi,

Thank you for the replies. I've removed line 15, and instead call this from within each of the two required methods, mousePressed and updateLocation, but I still can't get the PacMan to be dragged or redrawn. What am I missing here? Why does the PacMan drawing not get repainted when I drag it?

Any help?

Thanks
CEHJCommented:
You're trying to set the location of the entire component. You should be setting the location (coordinates) of the image
nhay59Author Commented:
Hi,

I'm really sorry, I don't see what you mean.

Currently, I get the position of the PacMan drawing in the mousePressed() method, and then set the location of the new drawing in the updateLocation() method, and then repaint the window. Why does it not simply use the code from the paintComponent() to redraw the PacMan drawing in the new position?

Any help?

Thanks
CEHJCommented:
pacman.setLocation

is what you're doing. You need to set the position of the drawing
Manikandan ThiagarajanSenior consultantCommented:
In mouse drag method you call the repaint method

could you post the pacman class now?
Manikandan ThiagarajanSenior consultantCommented:
sorry ,Area class
nhay59Author Commented:
Hi,

All the required code to draw the PacMan object is in the above code, The class Area is a standard Java class, which can be viewed at the following address,

http://java.sun.com/j2se/1.3/docs/api/java/awt/geom/Area.html

The problem with the above code is that it is simply not dragging and then redrawing the PacMan in a new location when the user clicks and then releases the mouse button.

Any help really appreciated. I've tried going through online tutorials and examples and just can't seem to see the problem with this one.

Thanks
Manikandan ThiagarajanSenior consultantCommented:
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.util.*;

public class PacMan_clickstest extends JPanel implements MouseListener, MouseMotionListener{
   
    public static int mode = 0;
    private static JButton rightButton;
    private static JButton leftButton;
    int last_x, last_y;
    boolean pressOut = false;
       static PacMan_clickstest pacman;
   
    public PacMan_clickstest(){
       
        addMouseListener(this);
        addMouseMotionListener(this);
       
    }
   
    public void mousePressed(MouseEvent e) {
        //PacMan_clickstest pacman = new PacMan_clickstest();
       
        last_x = e.getX();
        last_y = e.getY();
       pressOut = pacman.contains(e.getX(), e.getY());
    }
   
    public void mouseDragged(MouseEvent e){
        if ( !pressOut)
            updateLocation(e);
        repaint();
    }
   
    public void mouseReleased(MouseEvent e) {}
    public void mouseMoved(MouseEvent e){}
    public void mouseClicked(MouseEvent e){}
    public void mouseExited(MouseEvent e){}
    public void mouseEntered(MouseEvent e){}
   
    public void updateLocation(MouseEvent e) {
        //PacMan_clickstest pacman = new PacMan_clickstest();
       
        pacman.setLocation(e.getX() - last_x, e.getY() - last_y);
        last_x = e.getX();
        last_y = e.getY();
       
       
    }
   
    public void paintComponent(Graphics g) {
        Dimension d = getSize();
       
        Graphics2D g2 = (Graphics2D)g;
       
        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));
        g2.setPaint(Color.yellow);
        g2.fill(pacman);
        g2.setPaint(Color.black);
        g2.draw(pacman);
    }
   
    public static void main(String[] args) {
        JFrame frame = new JFrame("Drawing stuff");
        Container contentPane = frame.getContentPane();
       
        JPanel panel = new JPanel();
        pacman = new PacMan_clickstest();
       
        leftButton = new JButton("Left");
        //leftButton.addActionListener(pacman);
        panel.add(leftButton);
       
        rightButton = new JButton("Right");
        //rightButton.addActionListener(pacman);
        panel.add(rightButton);
       
        contentPane.add(panel, BorderLayout.SOUTH);
        contentPane.add(pacman, BorderLayout.CENTER);
       
        frame.setSize(600, 600);
        frame.setVisible(true);
       
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
    }
}
check this code  and tell me your exact output
nhay59Author Commented:
Hi,

Thanks for the reply. When I run the program I get the usual window, which includes a pacman drawing in the top left corner, and two buttons along the bottom portion of the window. When I try to drag the pacman drawing nothing happens, including no output in the console. When I press the exit button, the program closes as usual.

It's as if the program is not hearing the mouse dragging or simply doesn't know what to redraw.

I'm really getting confused as to why this won't work.

Any help or advice really appreciated.

Thanks.
CEHJCommented:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.image.BufferedImage;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class PacMan2Clicks extends JFrame implements ActionListener,
            MouseMotionListener {

      public static int mode = 0;

      private static JButton rightButton;

      private static JButton leftButton;

      private Image pacmanImage;

      private int pacManX, pacManY;

      public PacMan2Clicks() {

            Container contentPane = getContentPane();

            JPanel panel = new JPanel() {
                  public void paintComponent(Graphics g) {

                        super.paintComponent(g);
                        if (pacmanImage == null) {
                              createPacmanImage();
                        } else {
                              g.drawImage(pacmanImage, pacManX, pacManY,
                                          pacmanImage.getWidth(this), pacmanImage.getHeight(this), this);
                        }
                  }
            };

            panel.addMouseMotionListener(this);
            JPanel buttonPanel = new JPanel();
            leftButton = new JButton("Leftt");
            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 createPacmanImage() {
            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));

            Rectangle pacmanBounds = pacman.getBounds();
            pacmanImage = new BufferedImage(pacmanBounds.width, pacmanBounds.height,
                        BufferedImage.TYPE_INT_RGB);
            Graphics2D g2 = (Graphics2D) pacmanImage.getGraphics();
            g2.setPaint(Color.yellow);
            g2.fill(pacman);
            g2.draw(pacman);

            System.out.println(pacmanImage);

            repaint();

      }

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

      public void mouseDragged(MouseEvent e) {
            pacManX = e.getX();
            pacManY = e.getY();
            repaint();
      }

}
CEHJCommented:
Actually - you don't need the offscreen image:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class PacMan2Clicks extends JFrame implements ActionListener,
            MouseMotionListener {

      public static int mode = 0;

      private static JButton rightButton;

      private static JButton leftButton;

      private Image pacmanImage;

      private int pacmanX, pacmanY;

      public PacMan2Clicks() {

            Container contentPane = getContentPane();

            JPanel panel = new JPanel() {
                  public void paintComponent(Graphics g) {
                        super.paintComponent(g);
                        setPacman(g);
                  }
            };

            panel.addMouseMotionListener(this);
            JPanel buttonPanel = new JPanel();
            leftButton = new JButton("Leftt");
            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);

      }

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

      public void mouseDragged(MouseEvent e) {
            pacmanX = e.getX();
            pacmanY = e.getY();
            repaint();
      }

      public void mouseMoved(MouseEvent e) {
      }
}

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,

That is brilliant. Thank you so much for all your help. I was reading through an example online with a bufferedImage, but just couldn't see how to use it with this example. To now see an example is great. And it works perfectly as well.

Have a great weekend.

Thanks
CEHJCommented:
:-)
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
Editors IDEs

From novice to tech pro — start learning today.