0

hi i have some code in java that draws a rectangle, hwever itll only drag right, even if i drag left itll drag to the right, here is the code i have any help please?

  public void mouseDragged(MouseEvent e) {
                    Point p = e.getPoint();
                    int width = Math.max(selection.x - e.getX(), e.getX() - selection.x);
                    int height = Math.max(selection.y - e.getY(), e.getY() - selection.y);
                    selection.setSize(width, height);
                    repaint();
user1757913
  • 53
  • 1
  • 11

2 Answers2

4

Remember, Rectangle (and Graphics#fillRect and Graphics#drawRect) won't render rectangles with negative width/heights

You need two things...

  1. The current mouse point (or drag point in your case)
  2. The point where the mouse was first pressed (anchor or origin point)

You should get the anchor point from the mousePressed event...

public void mousePressed(MouseEvent e) {
    clickPoint = new Point(e.getPoint());
}

You then need to make determinations about which point is the smallest and use that as the start and which is the largest and use those for dimensions.

public void mouseDragged(MouseEvent e) {
    int minX = Math.min(e.getX(), clickPoint.x);
    int minY = Math.min(e.getY(), clickPoint.y);
    int maxX = Math.max(e.getX(), clickPoint.x);
    int maxY = Math.max(e.getY(), clickPoint.y);

    selection.x = minX;
    selection.y = minY;
    selection.width = maxX - minX;
    selection.height = maxY - minY;
    repaint();
}

Selection Drag

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class SelectionExample {

    public static void main(String[] args) {
        new SelectionExample();
    }

    public SelectionExample() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

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

    public class TestPane extends JPanel {

        private Rectangle selection = new Rectangle();
        private Point clickPoint;

        public TestPane() {
            MouseAdapter ma = new MouseAdapter() {

                @Override
                public void mouseDragged(MouseEvent e) {
                    int minX = Math.min(e.getX(), clickPoint.x);
                    int minY = Math.min(e.getY(), clickPoint.y);
                    int maxX = Math.max(e.getX(), clickPoint.x);
                    int maxY = Math.max(e.getY(), clickPoint.y);

                    selection.x = minX;
                    selection.y = minY;
                    selection.width = maxX - minX;
                    selection.height = maxY - minY;
                    repaint();
                }

                @Override
                public void mousePressed(MouseEvent e) {
                    clickPoint = new Point(e.getPoint());
                }

            };

            addMouseListener(ma);
            addMouseMotionListener(ma);
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            if (selection.width > 0 && selection.height > 0) {
                g2d.setColor(new Color(0, 0, 255, 64));
                g2d.fill(selection);
                g2d.setColor(Color.BLUE);
                g2d.draw(selection);
            }
            g2d.dispose();
        }
    }

}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • thanks, its currently in mousedrag event, ive tried this but what should i add for int x and int y? thanks alot – user1757913 Mar 25 '14 at 20:49
  • Generally, you shouldn't add anything. What you need to do is determine the maxX and minX then the width would become maxX - minX and the x point would be minX, then, obviously, the same thing for y – MadProgrammer Mar 25 '14 at 21:02
  • to paint the rectangle i have selection.setSize(width, height);, – user1757913 Mar 25 '14 at 21:07
  • Right, so, see how I've calculated the location and size, you'd need to replace the painting of the selection with these values... – MadProgrammer Mar 25 '14 at 21:10
  • hm iv done what youve said, it now paints a rectanglw when i click but wont drag, ill keep trying with info youve given, Thanks! – user1757913 Mar 25 '14 at 21:22
  • @user1757913 Sorry, my bad :P - You need to maintain some kind of reference to the original click point, I've updated the answer and included a runnable example ;) – MadProgrammer Mar 25 '14 at 23:07
  • Thats perfect, thank you very much for yout help, best answer – user1757913 Mar 25 '14 at 23:54
  • @user1757913 Glad we got there in the end. That will teach me for posting from my iPad, with my left hand, first thing in the morning :P – MadProgrammer Mar 26 '14 at 00:04
  • haha no worries and i thank you! also on the part where its new jframe"testing" etc how would i make the new JFrame basically transparent but still visible if you get what i mean lol – user1757913 Mar 26 '14 at 00:15
  • Do you mean something like [this](http://stackoverflow.com/questions/13948122/drawing-a-bounding-rectangle-to-select-what-area-to-record/13948198#13948198), select a portion of the screen? As another [example](http://stackoverflow.com/questions/15776549/create-rectangle-with-mouse-drag-not-draw/15776976#15776976) – MadProgrammer Mar 26 '14 at 00:18
  • hi me again, regarding the first example under 'this' how would i go about taking a screenshot of the inside of rectangle on mouse up, ive added an override and mouserelease function but no luck, thanks – user1757913 Mar 26 '14 at 21:34
  • From what I remember, you would need to override the `mouseReleased` method of the `MouseAdapter` in the `SnipItPane`. When triggered, you would need to obtain the dimensions of the `selectionPane`, because of the way the window has been setup, this should be already been in the screen context. You would then need to hide the window that the `SnipItPane` is contained in and use `Robot` to capture the screen area (using the dimensions you obtained from the `SelectionPane`) – MadProgrammer Mar 26 '14 at 22:57
0

Let's do some simple algebra.

selection.x - e.getX()

is the same as

- (e.getX() - selection.x)

so your expression is saying:

Math.max(- (e.getX() - selection.x), e.getX() - selection.x)

And since the positive version will always be bigger, it will always choose the positive answer, and thus you will never get a rectangle with a negative width/height.

ASKASK
  • 657
  • 8
  • 16