javaswingawtpolygonmouselistener

moving Polygon shapes with mouseDragged


I am writing a pentomino game, but there was a problem with moving the pieces. The shapes move, but the coordinates of the polygon borders with each move do not actually correspond to the polygon borders, and moving the shapes becomes impossible.

That's what I did:

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;

public class MyPanel extends JFrame implements MouseListener, MouseMotionListener {
    Boolean isPressed = false;
    JPanel mainPane;
    Container contentPane;
    Point offset;
    ArrayList<Polygon> polygons = new ArrayList<Polygon>();
    Polygon fig1 = new Polygon(new int[]{50, 90, 90, 50}, new int[]{50, 50, 200, 200}, 4);
    Polygon fig2 = new Polygon(new int[]{170, 250, 250, 210, 210, 170, 170, 130, 130, 170}, new int[]{80, 80, 120, 120, 200, 200, 160, 160, 120, 120}, 10);
    Polygon fig3 = new Polygon(new int[]{370, 410, 410, 330, 330, 370}, new int[]{90, 90, 200, 200, 160, 160}, 6);
    /*Polygon fig4 = new Polygon(new int[]{50, 90, 90, 50}, new int[]{50, 50, 200, 200}, 4);
    Polygon fig5 = new Polygon(new int[]{50, 90, 90, 50}, new int[]{50, 50, 200, 200}, 4);
    Polygon fig6 = new Polygon(new int[]{50, 90, 90, 50}, new int[]{50, 50, 200, 200}, 4);
    Polygon fig7 = new Polygon(new int[]{50, 90, 90, 50}, new int[]{50, 50, 200, 200}, 4);
    Polygon fig8 = new Polygon(new int[]{50, 90, 90, 50}, new int[]{50, 50, 200, 200}, 4);
    Polygon fig9 = new Polygon(new int[]{50, 90, 90, 50}, new int[]{50, 50, 200, 200}, 4);
    Polygon fig10 = new Polygon(new int[]{50, 90, 90, 50}, new int[]{50, 50, 200, 200}, 4);
    Polygon fig11 = new Polygon(new int[]{50, 90, 90, 50}, new int[]{50, 50, 200, 200}, 4);
    Polygon fig12 = new Polygon(new int[]{50, 90, 90, 50}, new int[]{50, 50, 200, 200}, 4);*/
    int x, y;

    MyPanel(){
        polygons.add(fig1);
        polygons.add(fig2);
        polygons.add(fig3);

        mainPane = new JPanel(){
            public void paintComponent(Graphics g){
                super.paintComponent(g);
                Graphics2D g2 = (Graphics2D) g;

                for(Shape fig: polygons){
                    g2.setColor(Color.BLUE);
                    g2.fill(fig);
                }
            }
        };

        contentPane = this.getContentPane();
        contentPane.add(mainPane);
        mainPane.setLayout(null);

        setVisible(true);
        setSize(1000, 600);
        setResizable(false);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

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

    public void mousePressed(MouseEvent e) {
        for(Polygon polygon: polygons) {
            if (polygon.getBounds().contains(e.getPoint())) {
               //offset = new Point(e.getPoint().x - polygon.getBounds().x, e.getPoint().y - polygon.getBounds().y);
                x = e.getX();
                y = e.getY();
            }
        }
    }

    public void mouseClicked(MouseEvent e){}
    public void mouseReleased(MouseEvent e){}
    public void mouseEntered(MouseEvent e){}
    public void mouseExited(MouseEvent e){}

    public void mouseDragged(MouseEvent e) {
        if(e.getSource() == mainPane) {
            for(Polygon polygon: polygons) {
                if (polygon.getBounds().contains(x, y)) {
                    int dx = e.getX() - x;
                    int dy = e.getY() - y;
                    for (int i = 0; i < polygon.npoints; i++) {
                        polygon.xpoints[i] += dx;
                        polygon.ypoints[i] += dy;
                        repaint();
                    }
                    x += dx;
                    y += dy;
                }
            }
        }
    }
    public void mouseMoved(MouseEvent e){}
}

I understand that the problem lies somewhere here:


    public void mouseDragged(MouseEvent e) {
        if(e.getSource() == mainPane) {
            for(Polygon polygon: polygons) {
                if (polygon.getBounds().contains(x, y)) {
                    int dx = e.getX() - x;
                    int dy = e.getY() - y;
                    for (int i = 0; i < polygon.npoints; i++) {
                        polygon.xpoints[i] += dx;
                        polygon.ypoints[i] += dy;
                        repaint();
                    }
                    x += dx;
                    y += dy;
                }
            }
        }
    }

But I do not understand how to solve it, please tell me what is the problem.


Solution

  • The problem

    The Polygon class stores the calculated bounding box (instance of Rectangle), so it must not be re-calculated every time it is needed. The cached bounding box is not re-calculated if the coordinates of the Polygon are changed directly (xpoints and ypoints).

    Solutions:

    1. use the translate() method of Polygon to translate its points - it will clear the cached bounding box, forcing it to be re-calculated; or

    2. use the invalidate() method of Polygon, after changing all points, to delete the cached bounding box and force its re-calculation.

    IMO the first point should be preferred: no loop needed, better describes the intention.


    Notes: