Issue drawing rectangle in negative direction - Java

3.6k views Asked by At

I'm having issues attempting to draw a rectangle in the negative direction from a point clicked on a screen. I have the following class that simulates a screen capture software like Gyazo:

class DrawSquare extends JPanel implements MouseListener, MouseMotionListener {

// Components
public JDialog frame;
public Rectangle rectangle;
public BufferedImage bufferedImage;
public Point start, end;

// Variables
public String capturedImage;

public DrawSquare(JDialog frame) {

    this.frame = frame;

    // Read in crosshair image to replace mouse icon
    Toolkit tool = Toolkit.getDefaultToolkit();
    Image newImage = getToolkit().getImage("components/cursor.png");
    Cursor cursor = tool.createCustomCursor(newImage, new Point (this.frame.getX(), this.frame.getY()), "img");

    this.frame.setCursor(cursor);
    this.frame.addMouseListener(this);
    this.frame.addMouseMotionListener(this);

}

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

    Graphics2D g2d = (Graphics2D) g.create();
    // draw background overlay
    g2d.drawImage(bufferedImage, WIDTH, 0, this);
    if (rectangle != null) {
        //g2d.setColor(new Color(225, 225, 255, 128));
        frame.setOpacity(0.6f);
        //g2d.fill(rectangle);
        System.out.println(rectangle);
        g2d.setColor(new Color(72,119,205));
        g2d.draw(rectangle);
    }
    g2d.dispose();
}

@Override
public void mouseDragged(MouseEvent e) {

    this.end = e.getPoint();
    int width = end.x - start.x;
    int height = end.y - start.y;

    rectangle.setSize(new Dimension(width, height));
    frame.validate();
    frame.repaint();
}

@Override
public void mouseMoved(MouseEvent e) {
    this.start = e.getPoint();
    frame.validate();
    frame.repaint();
}


@Override
public void mousePressed(MouseEvent e) {
    // Get the X and Y point from the mouse pressed
    rectangle = new Rectangle(start);
    System.out.println(rectangle);
    // Repaint the screen
    frame.validate();
    frame.repaint();
}

@Override
public void mouseReleased(MouseEvent e) {}

@Override
public void mouseClicked(MouseEvent e) {}

@Override
public void mouseEntered(MouseEvent e) {}

@Override
public void mouseExited(MouseEvent e) {}

}

Now the reason for the issue as mentioned already, is that when I attempt to draw the rectangle box in the opposition or negative direction of a point clicked on the screen, it doesn't draw, the rectangle information looks like this during such an attempt:

java.awt.Rectangle[x=635,y=395,width=-316,height=-194]

However, when I drag the rectnagle in the positive direction it works as it is supposed to:

enter image description here

What I'd like to know is how I can fix this using negative values for width/height, or doing it another way entirely.

2

There are 2 answers

1
StanislavL On BEST ANSWER

You should actually have 2 Points - drag start Point and current drag Point.

The rectangle is calculated:

x=min(dragStartPoint.x, dragCurrentPoint.x)
y=min(dragStartPoint.y, dragCurrentPoint.y)
width=abs(dragStartPoint.x - dragCurrentPoint.x)
height=abs(dragStartPoint.y - dragCurrentPoint.y)
2
Joop Eggen On

Increasing width and height are okay. When they decrease, and reach 0, you need to decrease x and y.

Or otherwise seen: a rectangle is between two diagonal point topleft and bottomright. These roles change when for one coordinate (x or y) they cross.


Positive: you drag the bottom-right point (I guess). Both coordinates zero: TL and BT cooincide, W and H zero. Both coordinates negative: you leave the bottom-right point at the left-right position and drag the top-left point of the rectangle, W and H increasing from 0.

The easiest is:

  • Keep the mouse-down point from
  • Trag the mouse-drag point to

Calculate the rectangle between them:

Point min = new Point(Math.min(from.x, to.x), Math.min(from.y, to.y));
Point max = new Point(Math.max(from.x, to.x), Math.max(from.y, to.y));

Then the rectangle is calculated easily.