Link to home
Start Free TrialLog in
Avatar of nhay59
nhay59

asked on

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
Avatar of zzynx
zzynx
Flag of Belgium image

a stack overflow on such kind of a line... Must be something with recursivity
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
>>//PacMan_clickstest pacman = new PacMan_clickstest();

Is not required. Just reset the position
Oooo, of course!
Why do you have

>>   PacMan_clickstest pacman = new PacMan_clickstest();

that line?
You call the constructor in the constructor in the constructor ....
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(){
Avatar of nhay59
nhay59

ASKER

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
You're trying to set the location of the entire component. You should be setting the location (coordinates) of the image
Avatar of nhay59

ASKER

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
pacman.setLocation

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

could you post the pacman class now?
sorry ,Area class
Avatar of nhay59

ASKER

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
SOLUTION
Avatar of Manikandan Thiagarajan
Manikandan Thiagarajan
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of nhay59

ASKER

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

}
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of nhay59

ASKER

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
:-)