I have written a program which allows the user to click on the screen which draws a circle and when the user clicks on the circle again they can drag it around. My code allows the circle to be dragged it still displays the original cirlce and draws the path the cricle takes rather than only displaying the circle being dragged. Here are my classes. I hope someone can spot the problem. Thank you

This displays the frame:

package finalproject;

public class RunApplication {
    public static void main(String[] args) {

        RunProgram prog = new RunProgram();
        prog.setSize(800, 500);
        prog.show();
    }
}

This just fills the frame:

/*
package finalproject;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.swing.*;
import javax.swing.JLabel;

public class RunProgram extends JFrame {

    static JMenuBar bar;
    File fileL;
    File fileR;
    private JPanel toolPanel;
    JButton openButton;
    static PicturePanel pic1, pic2;

    /** Creates a new instance of RunProgram */
    public RunProgram() {
        setLayout(new BorderLayout());

        //create panel to show original pictures
        pic1 = new PicturePanel();
        pic2 = new PicturePanel();

        toolPanel = new JPanel();
        toolPanel.setPreferredSize(new Dimension(100, 50));

        //create panel to show the phases

        JToolBar toolBar = new JToolBar("Still draggable");
        toolBar = new JToolBar(null, JToolBar.VERTICAL);
        toolBar.setFloatable(false);

        add(toolBar, BorderLayout.NORTH);
        add(pic1, BorderLayout.WEST);
        add(pic2, BorderLayout.EAST);
        add(toolBar, BorderLayout.CENTER);

    }
}

Here is the main code:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package finalproject;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.JPanel;

/**
 *
 * 
 */
public class PicturePanel extends JPanel implements MouseListener, MouseMotionListener {

    public PicturePanel() {
        this.setBorder(BorderFactory.createLoweredBevelBorder());
        this.addMouseListener(this);
        this.addMouseMotionListener(this);
        setPreferredSize(new Dimension(250, 150));
        setVisible(true);

    }

    @Override
    public void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        for (Shape s : shapes) {
            g2.setColor(Color.RED);
            g2.fill(s);
            g2.setColor(Color.BLACK);
            g2.draw(s);
        }
    }
    ArrayList<Point> pointsLeft = new ArrayList<Point>();
    ArrayList<Point> pointsRight = new ArrayList<Point>();
    public int lx,  ly,  rx,  ry;
    public Point eR1,  eR2,  eL1,  eL2;
    public Point lil;
    public Point lil2;
    ArrayList<Shape> shapes = new ArrayList<Shape>();

    public void mouseClicked(MouseEvent e) {
        if (e.getSource() == RunProgram.pic1) {
            eL1 = e.getPoint();
            lx = eL1.x;
            ly = eL1.y;
            drawCircleLeft(eL1.x, eL1.y);
            System.out.println("eL1 = " + eL1);
        }
    }

    public void printPointsLeft() {
        System.out.println(pointsLeft);
    }

    public void printPointsRight() {
        System.out.println(pointsRight);
    }
//method to determine which shape is under the cursor using the contains() 
    //method of each Shape against your mouse coordinates
    private Shape hitTest(Point p) {
        Shape hitShape = null;
        for (Shape testShape : shapes) {
            if (testShape.contains(p)) {
                hitShape = testShape;
                break;
            }
        }
        return hitShape;
    }
    
private void moveC(int x, int y){
    if (eL1.x !=x || eL1.y !=y){
            repaint(lx + (x - lx), ly + (y - ly),(2 * radius)+1, (2 * radius));
            eL1.x = x;
            eL1.y = y;
            repaint(lx + (x - lx), ly + (y - ly), (2 * radius) + 1, (2 * radius)+1);
}
}
    public void mouseDragged(MouseEvent e) {
        moveC(e.getX(), e.getY());
    }
    
    public void drawCircleLeft(int x, int y) {
        Shape circle = new Ellipse2D.Double(x - radius, y - radius, 2 * radius, 2 * radius);
        shapes.add(circle);
        repaint(x - radius, y - radius, 2 * radius, 2 * radius);
    }

    public void drawCircleRight(int x, int y) {
        Shape circle = new Ellipse2D.Double(x - radius, y - radius, 2 * radius, 2 * radius);
        shapes.add(circle);
        repaint(x - radius, y - radius, 2 * radius, 2 * radius);
    }

    public void mousePressed(MouseEvent e) {
        if (e.getSource() == RunProgram.pic1) {
            startPoint = e.getPoint();
            lx = startPoint.x;
            ly = startPoint.y;
        }
        if (e.getSource() == RunProgram.pic2) {
            startPoint = e.getPoint();
            rx = startPoint.x;
            ry = startPoint.y;
        }
    }

    public void mouseReleased(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
    }
    int x, y;
    int radius = 10;
    Point startPoint;

    public void mouseMoved(MouseEvent e) {
    }

    public void mouseEntered(MouseEvent e) {
    }
}

Recommended Answers

All 10 Replies

Sounds like the problem is that your screen never clears so everything you ever painted is painted on the JPanel every time. Nothing gets erased.

@Override
    public void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        for (Shape s : shapes) {
            g2.setColor(Color.RED);
            g2.fill(s);
            g2.setColor(Color.BLACK);
            g2.draw(s);
        }
    }

Try putting this line at the top of this function and see if the problem goes away:

super.paintComponent (g);

From series of PMs on this:

Hi, I have implemented the dragging however because in the example you gave me the paint draws everything in the shapes arraylist so when i drag a shape the orignal position is drawn. Also the path which the circle is dragged is also drawn. I don't know why that is. I'm also not too sure how to use your hitTest method. If it returns the shape under the cursor how would i then use that to select the shape, for example by colouring it a different colour and then implementing the move? Sorry for so many questions. I really hope you can help. Thank you for the help you'v given so far.

My example showed how to select one of the shapes with the mouse click and move it when dragged. Your current code adds a new shape on click. You need to decide which you want to do, because you can't do both at the same time. You could use right/left click or modifiers like shift to separate the operations.

That is the problem I am having. I need to be able to draw the circle where the mouse is clicked. Then be able to select the circle and move it to a new position. I don't know how to do that.

And I alrady explained that you need to separate the two actions into two different mouse events, unless you want to first do the hitTest to check for a circle under the mouse and create one if there is not one already there.

So this separates easily:
mouseClicked > is circle already there?
If yes > select circle.
If no > create circle, add to shape list, select circle.

Mouse drag operation remains the same. If selected circle ref is not null, move it with the mouse point.

public void mouseClicked(MouseEvent e) {
        if (e.getSource() == RunProgram.pic1) {
            Shape shaaa = hitTest(e.getPoint());
            if(hitTest(e.getPoint()) != null){
                //select shape <<<<<<<<< how would i select the shape
            } else if (hitTest(e.getPoint()) == null){
            eL1 = e.getPoint();
            //pointsLeft.add(eL1);
            lx = eL1.x;
            ly = eL1.y;
            drawCircleLeft(eL1.x, eL1.y);
            System.out.println("eL1 = " + eL1);
            }

I understand what you have written but my problem is still with how do I actually select the shape. the hitTest method returns a shape which i have stored in a variable but would I then change the colour of the shape or highlight it in some way?

You'll see in my example that I stored the selected shape in a class level variable called mouseOverShape. You could call that selectedShape if you wish. When you loop through the shapes list, if shape==selectedShape you can draw the border a different color or whatever you like. The point is to set a reference to the selected shape, do whatever you need to do, and then null that reference on mouseReleased.

Let's keep further questions on this here in the thread. The example that I refer to is this post on a previous thread: http://www.daniweb.com/forums/post951298-28.html

Inside PicturePanel : remove all conditions

//if (e.getSource() == RunProgram.pic1) {/...
or
 //if (e.getSource() == RunProgram.pic2) {/...

and by default initilaize eL1 in constructor: eL1 = new Point(0, 0); to avoid NullPoiterException
It should work!
Later reduce doubled number or varibles , for example pointsLeft/pointsRight , same make with functions.

I've tried doing all that you've said but for some reason the output is still the same. When I click a circle that is already been drawn, it is not coloured green which it should be.

package finalproject;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.JPanel;

/**
 *
 */
public class PicturePanel extends JPanel implements MouseListener, MouseMotionListener {

    public PicturePanel() {
        this.setBorder(BorderFactory.createLoweredBevelBorder());
        this.addMouseListener(this);
        this.addMouseMotionListener(this);
        setPreferredSize(new Dimension(250, 150));
        setVisible(true);

    }

    @Override
    public void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        for (Shape s : shapes) {
            if (s == selectedShape) {
                g2.setColor(Color.GREEN);
                g2.fill(s);
                g2.setColor(Color.BLACK);
                g2.draw(s);
            }
            g2.setColor(Color.RED);
            g2.fill(s);
            g2.setColor(Color.BLACK);
            g2.draw(s);
        }
    }
    ArrayList<Point> pointsLeft = new ArrayList<Point>();
    ArrayList<Point> pointsRight = new ArrayList<Point>();
    public  int lx,    ly,    rx,    ry;
    public  Point eR1,   eR2 ,   eL1 ,   eL2 ;
    public Point lil;
    public Point lil2;
    ArrayList<Shape> shapes = new ArrayList<Shape>();
    private Shape selectedShape = null;

    public void mouseClicked(MouseEvent e) {
        if (e.getSource() == RunProgram.pic1) {

            if (selectedShape != null) {
                drawSelectedLeft(eL1.x, eL1.y);
            } else if (hitTest(e.getPoint()) == null) {
                eL1 = e.getPoint();
                //pointsLeft.add(eL1);
                lx = eL1.x;
                ly = eL1.y;
                drawCircleLeft(eL1.x, eL1.y);
                System.out.println("eL1 = " + eL1);
            }

        }
    }

    public void printPointsLeft() {
        System.out.println(pointsLeft);
    }

    public void printPointsRight() {
        System.out.println(pointsRight);
    }
//method to determine which shape is under the cursor using the contains() 
    //method of each Shape against your mouse coordinates
    private Shape hitTest(Point p) {
        Shape hitShape = null;
        for (Shape testShape : shapes) {
            if (testShape.contains(p)) {
                hitShape = testShape;
                break;
            }
        }
        return hitShape;
    }

    private void moveC(int x, int y) {
        if (eL1.x != x || eL1.y != y) {
            eL1.x = x;
            eL1.y = y;
            repaint(lx + (x - lx), ly + (y - ly), (2 * radius), (2 * radius));
        }
    }

    public void mouseDragged(MouseEvent e) {
        dragging = true;
        if (selectedShape != null) {
            moveC(e.getX(), e.getY());
        }
    }

    public void drawCircleLeft(int x, int y) {
        Shape circle = new Ellipse2D.Double(x - radius, y - radius, 2 * radius, 2 * radius);
        shapes.add(circle);
        repaint(x - radius, y - radius, 2 * radius, 2 * radius);
    }

        public void drawSelectedLeft(int x, int y) {
        Shape circle = new Ellipse2D.Double(x - radius, y - radius, 2 * radius, 2 * radius);
        selectedShape = circle;
        shapes.add(selectedShape);
        repaint(x - radius, y - radius, 2 * radius, 2 * radius);
    }

    public void drawCircleRight(int x, int y) {
        Shape circle = new Ellipse2D.Double(x - radius, y - radius, 2 * radius, 2 * radius);
        shapes.add(circle);
        repaint(x - radius, y - radius, 2 * radius, 2 * radius);
    }

    public void mousePressed(MouseEvent e) {
        if (e.getSource() == RunProgram.pic1) {
            selectedShape = hitTest(e.getPoint());
            startPoint = e.getPoint();
            lx = startPoint.x;
            ly = startPoint.y;
            dragging = false;
        }
        if (e.getSource() == RunProgram.pic2) {
            selectedShape = hitTest(e.getPoint());
            startPoint = e.getPoint();
            rx = startPoint.x;
            ry = startPoint.y;
            dragging = false;
        }
    }

    public void mouseReleased(MouseEvent e) {
        selectedShape = null;
    }

    public void mouseExited(MouseEvent e) {
    }
    int x,   y;
    int radius = 10;
    private boolean dragging = false;
    Point startPoint;

    public void mouseMoved(MouseEvent e) {
    }

    public void mouseEntered(MouseEvent e) {
    }
}

]
Try putting this line at the top of this function and see if the problem goes away:

super.paintComponent (g);

I tried this and it get rid of the problem, however now I cannot drag the circle.

Can anyone help please? I know I am so close to getting it to work but I just can't identify the problem.
Thank you

look at example ...jdk1.6.0_14/demo/applets/GraphLayout/example1.html
the same behavior

Where can I find that?

Thank you

http://java.sun.com/applets/jdk/1.4/
or with sun jdk install package.
Use also this code in main method

public static void main(String[] args) {
        Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {

            public void eventDispatched(AWTEvent event) {
                System.out.println("AWTEventListener:eventDispatched " + event);
            }
        }, AWTEvent.MOUSE_EVENT_MASK + AWTEvent.MOUSE_MOTION_EVENT_MASK);
        RunProgram prog = new RunProgram();
//..

to trace mouse events

Thank you for all your help, i've finally managed to get it working.
Thanks

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.