0

This part of a larger assignment where the user must be able to draw, move, and resize squares, circles, and lines. Also, the processes must be visible.

I am having no trouble with squares and circles, but when I try to draw a line, then there's a problem.

This is the code that draws a line and still produces this mistake:

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Line2D;

import javax.swing.JFrame;

public class test extends JFrame implements MouseListener,
MouseMotionListener {
Point startDrag, endDrag;

/**
 * @param args
 */
public test() {

    this.addMouseListener(this);
    this.addMouseMotionListener(this);
}
public static void main(String[] args) {
    test frame = new test();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(500, 500);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
}
Shape r = null;
public void paint(Graphics g) {
    super.paint(g);

    Graphics2D g2 = (Graphics2D) g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setStroke(new BasicStroke(1));
    g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
            0.50f));

    if(startDrag != null && endDrag != null)
    {
        r = makeLine(startDrag.x, startDrag.y, endDrag.x,
            endDrag.y);
    }


    if(r != null)
        g2.draw(r);
}

@Override
public void mouseDragged(MouseEvent e) {
    endDrag = new Point(e.getX(), e.getY());
    repaint();

}

@Override
public void mouseMoved(MouseEvent arg0) {
    // TODO Auto-generated method stub

}

@Override
public void mouseClicked(MouseEvent me) {
    startDrag = new Point(me.getX(), me.getY());
    repaint();
}

@Override
public void mouseEntered(MouseEvent arg0) {
    // TODO Auto-generated method stub

}

@Override
public void mouseExited(MouseEvent arg0) {
    // TODO Auto-generated method stub

}

@Override
public void mousePressed(MouseEvent me) {
    startDrag = new Point(me.getX(), me.getY());
    endDrag = startDrag;
    repaint();

}

private Line2D.Float makeLine(int x1, int y1, int x2, int y2) {
    return new Line2D.Float(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1- x2), Math.abs(y1 - y2));
}
@Override
public void mouseReleased(MouseEvent me) {

    r = makeLine(startDrag.x, startDrag.y, me.getX(), me.getY());

    startDrag = null;
    endDrag = null;
    repaint();

}

}

I have just recently started to learn how to use awt and swing so any advice is appreciated.

paperplate
  • 17
  • 4
  • 2
    Try removing the startDrag in the mouseClicked method – MadProgrammer Dec 06 '13 at 07:13
  • 1
    *"so any advice is appreciated."* Don't extent from JFrame, you're not adding any (useful) functionality to it. Extend instead from something like JPanel and override the paintComponent method instead. Paint of top level containers like JFrame are responsible for painting many sub components and aren't double buffered – MadProgrammer Dec 06 '13 at 07:19
  • Thank you for the advice. With the original code, I have tried removing the startDrag in the mouseClicked method but there was no change. Now I am trying to extend the JPanel. If you know of any good tutorials on how it should be done could you post a link please? – paperplate Dec 06 '13 at 09:48
  • See also this related [example](http://stackoverflow.com/a/5797965/230513). – trashgod Dec 06 '13 at 12:16

1 Answers1

0

The primary problem is here...

private Line2D.Float makeLine(int x1, int y1, int x2, int y2) {
    return new Line2D.Float(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1- x2), Math.abs(y1 - y2));
}

Line doesn't care if the second x/y is less then or greater then the first (or a combination of either), it will simply draw a line from one point to the next.

Because you already have a start point and end point which represent the individual mouse events, you can simply use them as is

private Line2D.Float makeLine(int x1, int y1, int x2, int y2) {
    return new Line2D.Float(x1, y1, x2, y2);
}

I also removed the change to startPoint in the mouseClicked event as it will not do what you want ;)

Iv'e posted the code I used to test it, with some of the recommended changes I mad in the comments...

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Line2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class DrawLine extends JPanel implements MouseListener,
                MouseMotionListener {

    Point startDrag, endDrag;

    public DrawLine() {

        this.addMouseListener(this);
        this.addMouseMotionListener(this);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new DrawLine());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    Shape r = null;

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(200, 200);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setStroke(new BasicStroke(1));
        g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
                        0.50f));

        if (startDrag != null && endDrag != null) {
            System.out.println(startDrag + " - " + endDrag);
            r = makeLine(startDrag.x, startDrag.y, endDrag.x,
                            endDrag.y);
        }

        if (r != null) {
            g2.draw(r);
        }
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        endDrag = new Point(e.getPoint());
        repaint();

    }

    @Override
    public void mouseMoved(MouseEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseClicked(MouseEvent me) {
//        startDrag = new Point(me.getX(), me.getY());
//        repaint();
    }

    @Override
    public void mouseEntered(MouseEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseExited(MouseEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mousePressed(MouseEvent me) {
        startDrag = new Point(me.getPoint());
        repaint();

    }

    private Line2D.Float makeLine(int x1, int y1, int x2, int y2) {
        return new Line2D.Float(x1, y1, x2, y2);
    }

    @Override
    public void mouseReleased(MouseEvent me) {

        r = makeLine(startDrag.x, startDrag.y, me.getX(), me.getY());

        startDrag = null;
        endDrag = null;
        repaint();

    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366