DommyCastles
DommyCastles

Reputation: 425

Drawing a line from 2 mouse clicks

I am trying to draw a line from a series of mouse clicks.

For example, when i click from one point on the screen to the next, it connects up the lines, and then i can keep clicking to next points where it continues to draw a continuous drawing line.

An example is here: http://oneslime.net/java/Tutorial_2 under Exercise 2

I believe there is some error in my logic (does not draw lines, just a point), but I just can't seem to find it!

Can anybody help me out?

Here is my code:

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

public class RoadCreator extends JPanel {

    private MouseHandler mouseHandler = new MouseHandler();

    private Point previousPoint = new Point();
    private Point nextPoint = new Point();
    private boolean drawing;

    public RoadCreator() {
        this.setPreferredSize(new Dimension(640, 480));
        this.addMouseListener(mouseHandler);
       this.addMouseMotionListener(mouseHandler);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setColor(Color.blue);
        g2d.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setStroke(new BasicStroke(8,
            BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL));
        g.drawLine(previousPoint.x, previousPoint.y, nextPoint.x, nextPoint.y);
    }

    private class MouseHandler extends MouseAdapter {

        @Override
        public void mousePressed(MouseEvent e) {
            drawing = true;
            nextPoint = e.getPoint();
            repaint();
            previousPoint = e.getPoint();

        }
    }

    public void display() {
        JFrame f = new JFrame("Road Creator");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setVisible(true);
    }

    }

Any help would be GREATLY appreciated, thank you!

Upvotes: 0

Views: 8925

Answers (3)

Richard Chassereau
Richard Chassereau

Reputation: 468

I have found a way to accomplish this task with as little effort as possible. However this does not equate to a "good" way of creating the application. You would need to account for future scalability such as the ability to draw other objects...etc. So let's just get down to how to make it work.

1) Let's omit the paintComponent method...I believe this should be paint().

    //@Override
    /*protected void paintComponent(Graphics g) {
         //Do Something...
      }*/

2) Let's add this method:

    public void drawLineHelper(Point prev, Point next){
        Graphics g = getGraphics();
        g.setColor(Color.blue);
        g.drawLine(previousPoint.x, previousPoint.y, nextPoint.x, nextPoint.y);
    }

3) Lastly, we need to make a few changes to the mouseHandler class:

   private class MouseHandler extends MouseAdapter {
        //twoPoints make sure we have two points.
        boolean twoPoints=false;

        @Override
        public void mousePressed(MouseEvent e) {
            if(twoPoints==false){
                nextPoint = e.getPoint();
                twoPoints = true;
            }
            else{
                //Set previous to next from now on.
                previousPoint = nextPoint;

                //Get a new next point.
                nextPoint = e.getPoint();

                //Helper method will draw the line each time.
                drawLineHelper(previousPoint,nextPoint);
                //repaint() no longer necessary.

            }
        }
    }

Here is a quick reference to another example with the same problem. The last post on the page explains this same method: http://www.ozzu.com/programming-forum/java-repainting-problem-t49362.html

Upvotes: 0

Andrew Thompson
Andrew Thompson

Reputation: 168845

Use a GeneralPath or Path2D instead.

The GeneralPath class represents a geometric path constructed from straight lines, and quadratic and cubic (Bézier) curves. It can contain multiple subpaths.

enter image description here

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

public class RoadCreator extends JPanel {

    private MouseHandler mouseHandler = new MouseHandler();

    GeneralPath path = null;
    private boolean drawing = false;

    public RoadCreator() {
        this.setPreferredSize(new Dimension(320, 200));
        this.addMouseListener(mouseHandler);
        this.addMouseMotionListener(mouseHandler);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setColor(Color.blue);
        g2d.setRenderingHint(
                RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setStroke(new BasicStroke(8,
                BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL));
        if (path!=null) {
            g2d.draw(path);
        }
    }

    private class MouseHandler extends MouseAdapter {

        @Override
        public void mousePressed(MouseEvent e) {
            Point p = e.getPoint(); 
            if (!drawing) {
                path = new GeneralPath();
                path.moveTo(p.x, p.y);
                drawing = true;
            } else {
                path.lineTo(p.x, p.y);
            }

            repaint();
        }
    }

    public void display() {
        JFrame f = new JFrame("Road Creator");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setVisible(true);
    }

    public static void main(String[] args) {
        RoadCreator rc = new RoadCreator();
        rc.display();
    }
}

Upvotes: 6

MadProgrammer
MadProgrammer

Reputation: 347332

This won't work.

public void mousePressed(MouseEvent e) {
    drawing = true;
    nextPoint = e.getPoint();
    repaint();
    previousPoint = e.getPoint();
}

You're assuming that repaint is a inline call (ie it paints before returning). It doesn't, repaint will queue a request to the repaint manager that will update at some time in the future.

public void mousePressed(MouseEvent e) {
    drawing = true;
    previousPoint = nextPoint
    nextPoint = e.getPoint();
    repaint();
}

Should work, just be aware, previousPoint will be null until the user clicks a second time.

Upvotes: 1

Related Questions