0

I have a program which draws 2 rectangles in a JFrame. I would like that when I drag and move (for resize), one of the rectangles, the second one move simultaneously. So, when you move the inferior border of the rectangle above, the superior border of the rectangle below moves in the same direction.

Edit: I am a beginner in Java programming, and I do not see at all how to do this.

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

class Resizing extends JPanel {
Rectangle rect = new Rectangle(100,100,150,150);
Rectangle rect2 = new Rectangle(100,250,150,100);

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D)g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setColor(new Color(0, 0, 200));
    g2.fill(rect);
    g2.setColor(new Color(0, 0, 100));
    g2.fill(rect2);

}

public static void main(String[] args) {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Resizing test = new Resizing();
    Resizing test2 = new Resizing();

    Resizer resizer = new Resizer(test);
    Resizer2 resizer2 = new Resizer2(test2);

    test.addMouseListener(resizer);
    test2.addMouseListener(resizer2);

    test.addMouseMotionListener(resizer);
    test2.addMouseMotionListener(resizer2);

    f.add(test);
    f.add(test2);

    f.setSize(400,400);
    f.setLocation(100,100);
    f.setVisible(true);
}
}
class Resizer extends MouseAdapter {
Resizing component;
boolean dragging = false;
// Give user some leeway for selections.
final int PROX_DIST = 3;

public Resizer(Resizing r) {
    component = r;
}

public void mousePressed(MouseEvent e) {
    if(component.getCursor() != Cursor.getDefaultCursor()) {
        // If cursor is set for resizing, allow dragging.
        dragging = true;
    }
}

public void mouseReleased(MouseEvent e) {
    dragging = false;
}

public void mouseDragged(MouseEvent e) {
    if(dragging){
        Point p = e.getPoint();
        Rectangle r = component.rect;
        int type = component.getCursor().getType();
        int dx = p.x - r.x;
        int dy = p.y - r.y;
        switch(type) {
            case Cursor.N_RESIZE_CURSOR:
                int height = r.height - dy;
                r.setRect(r.x, r.y+dy, r.width, height);
                break;
            case Cursor.S_RESIZE_CURSOR:
                height = dy;
                r.setRect(r.x, r.y, r.width, height);
                break;
            default:
                System.out.println("unexpected type: " + type);
        }
        component.repaint();
    }
}

public void mouseMoved(MouseEvent e) {
    Point p = e.getPoint();
    if(!isOverRect(p)) {
        if(component.getCursor() != Cursor.getDefaultCursor()) {
            // If cursor is not over rect reset it to the default.
            component.setCursor(Cursor.getDefaultCursor());
        }
        return;
    }
    // Locate cursor relative to center of rect.
    int outcode = getOutcode(p);
    Rectangle r = component.rect;
    switch(outcode) {
        case Rectangle.OUT_TOP:
            if(Math.abs(p.y - r.y) < PROX_DIST) {
                component.setCursor(Cursor.getPredefinedCursor(
                                    Cursor.N_RESIZE_CURSOR));
            }
            break;
        case Rectangle.OUT_BOTTOM:
            if(Math.abs(p.y - (r.y+r.height)) < PROX_DIST) {
                component.setCursor(Cursor.getPredefinedCursor(
                                    Cursor.S_RESIZE_CURSOR));
            }
            break;
        default:    // center
            component.setCursor(Cursor.getDefaultCursor());
    }
}

/**
 * Make a smaller Rectangle and use it to locate the
 * cursor relative to the Rectangle center.
 */
private int getOutcode(Point p) {
    Rectangle r = (Rectangle)component.rect.clone();
    r.grow(-PROX_DIST, -PROX_DIST);
    return r.outcode(p.x, p.y);
}

/**
 * Make a larger Rectangle and check to see if the
 * cursor is over it.
 */
private boolean isOverRect(Point p) {
    Rectangle r = (Rectangle)component.rect.clone();
    r.grow(PROX_DIST, PROX_DIST);
    return r.contains(p);
}
}

class Resizer2 extends MouseAdapter {
Resizing component2;
boolean dragging2 = false;
// Give user some leeway for selections.
final int PROX_DIST2 = 3;

public Resizer2(Resizing r2) {
    component2 = r2;
}

    @Override
public void mousePressed(MouseEvent e2) {
    if(component2.getCursor() != Cursor.getDefaultCursor()) {
        // If cursor is set for resizing, allow dragging.
        dragging2 = true;
    }
}

    @Override
public void mouseReleased(MouseEvent e2) {
    dragging2 = false;
}

    @Override
public void mouseDragged(MouseEvent e2) {
    if(dragging2) {
        Point p2 = e2.getPoint();
        Rectangle r2 = component2.rect2;
        int type = component2.getCursor().getType();
        int dx2 = p2.x - r2.x;
        int dy2 = p2.y - r2.y;
        switch(type) {
            case Cursor.N_RESIZE_CURSOR:
                int height = r2.height - dy2;
                r2.setRect(r2.x, r2.y+dy2, r2.width, height);
                break;
            case Cursor.S_RESIZE_CURSOR:
                height = dy2;
                r2.setRect(r2.x, r2.y, r2.width, height);
                break;
            default:
                System.out.println("unexpected type: " + type);
        }
        component2.repaint();
    }
}

public void mouseMoved(MouseEvent e2) {
    Point p2 = e2.getPoint();
    if(!isOverRect(p2)) {
        if(component2.getCursor() != Cursor.getDefaultCursor()) {
            // If cursor is not over rect reset it to the default.
            component2.setCursor(Cursor.getDefaultCursor());
        }
        return;
    }
    // Locate cursor relative to center of rect.
    int outcode = getOutcode(p2);
    Rectangle r2 = component2.rect2;
    switch(outcode) {
        case Rectangle.OUT_TOP:
            if(Math.abs(p2.y - r2.y) < PROX_DIST2) {
                component2.setCursor(Cursor.getPredefinedCursor(
                                    Cursor.N_RESIZE_CURSOR));
            }
            break;
        case Rectangle.OUT_BOTTOM:
            if(Math.abs(p2.y - (r2.y+r2.height)) < PROX_DIST2) {
                component2.setCursor(Cursor.getPredefinedCursor(
                                    Cursor.S_RESIZE_CURSOR));
            }
            break;
        default:    // center
            component2.setCursor(Cursor.getDefaultCursor());
    }
}

/**
 * Make a smaller Rectangle and use it to locate the
 * cursor relative to the Rectangle center.
 */
private int getOutcode(Point p2) {
    Rectangle r2 = (Rectangle)component2.rect2.clone();
    r2.grow(-PROX_DIST2, -PROX_DIST2);
    return r2.outcode(p2.x, p2.y);
}

/**
 * Make a larger Rectangle and check to see if the
 * cursor is over it.
 */
private boolean isOverRect(Point p2) {
    Rectangle r2 = (Rectangle)component2.rect2.clone();
    r2.grow(PROX_DIST2, PROX_DIST2);
    return r2.contains(p2);
}
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045

2 Answers2

2

In this basic example, the mouseDragged() handler calculates dx and dy, the relative offsets that are applied to the object as the mouse is dragged. In your case, you would apply the same offset to both rectangles. In the more elaborate example cited here, a List<Node> named selected holds the currently selected nodes, and Node.updatePosition() updates the positions of all selected nodes.

Addendum: I am a beginner in Java programming, and I do not see at all how to do this.

When working with a new language or unfamiliar graphics library, I find it helpful to start with small examples. You might look at some of the alternatives approaches cited here and here.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
1

You need to use a MouseMotionListener. MouseListener will not work. you then need to override the mouseDragged()

class Resizing extends JPanel impelemts MouseMotionListener {
    ...
    @Override
    public void mouseDragged(MouseEvent e){
        ...
    }
    public void mouseMoved(MouseEvent e){}
}

When ever the mouse is dragged, it fires an MouseEvent. Using that event you can get that certain point at any given time when the mouse is being dragged

public void mouseDragged(MouseEvent e){
    Point p = e.getPoint();
}

The point is the location of the mouse. You can use its getX() and getY() methods to get the x and y location of the point at every given moment

You'll want x and y variables declared as class members to hold the point so you can use it in your paint method

int xLoc;
int yLoc;

In you mouseDragged you can make the x and y points of the MouseEvent fired to set your xLoc and yLoc. Then repaint

public void mouseDragged(MouseEvent e){
    Point p = e.getPoint();
    xLoc = p.getX();
    yLoc = p.getY();
    repaint();
}

In your paintComponent() method you'll use those xLoc and yLoc to paint your objects. So the at every drag of the mouse, the xLoc and yLoc will keep being update and keep repainting. Something like

g2.fill(new Rectangle2D.Double(xLoc, yLoc, 50, 50));
g2.fill(new Rectangle2D.Double(xLoc + 100, yLoc + 100, 50, 50))

UPDATE - example program. Try and run it

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


public class MoveRects extends JPanel {

    private static final int SCREEN_WIDTH = 600;
    private static final int SCREEN_HEIGHT = 600;
    int xLoc;
    int yLoc;

    public MoveRects(){
        addMouseMotionListener(new MouseMotionAdapter(){
            public void mouseDragged(MouseEvent e) {
                Point p = e.getPoint();
                xLoc = (int)p.getX();
                yLoc = (int)p.getY();
                repaint();
            }
        });
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.GREEN);
        g.fillRect(xLoc, yLoc, 50, 50);
        g.setColor(Color.RED);
        g.fillRect(xLoc + 300, yLoc, 50, 50);
    }

    public Dimension getPreferredSize() {
        return new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT);

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new MoveRects());
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

            }
        });
    }
}
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • I changed but it does not work. We can not even change the height of the rectangles with the mouse. – user3153920 Jan 03 '14 at 14:13
  • I'm not exactly sure what you're trying to accomplish, but see my **UPDATE** – Paul Samsotha Jan 03 '14 at 14:31
  • Ok, I will explain otherwise. Did you run my program ? I want to change the height of each blocks of a stacked bar graph with the mouse. If two blocks (rectangles) are stacked, I want that when the lower edge of the upper block is moved, it also moves the upper edge of the lower block. The cumulative total height is the same, but one of the blocks becomes thinner when the other becomes thicker. – user3153920 Jan 03 '14 at 14:54