简体   繁体   中英

How can I bring my shape that I painted with paintComponent and clicked with a mouse to front?

I have a program that painted three different shapes(circle, triangle, and square) and I try to drag them with a mouse. What I want to do is to bring to the front that shape that is clicked. Can I pass the argument together with repaint() to tell a program that for example circle that is clicked has to be painted last, or is it possible to create three different paint methods to keep track of paint ordning?

Another question is my if-loop, it works just fine to drag square through circle and triangle but circle and triangle take square along with them if the mouse is in the same area. Can I turn off a mouse listener for other figures while I drag one?

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;
import java.awt.geom.Ellipse2D;
import java.awt.Polygon;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class MouseMoveScale extends JPanel {

    public boolean first;

private Rectangle2D.Float myRect = new Rectangle2D.Float(50, 50, 100, 100);
private Ellipse2D.Float myCr = new Ellipse2D.Float(10,10, 100, 100);
private Polygon myTr   = new Polygon(new int []  {120, 60, 240}, new int[] {150, 200, 200}, 3);

MovingAdapter ma = new MovingAdapter();

public MouseMoveScale() {
    addMouseMotionListener(ma);
    addMouseListener(ma);
}
public void paintComponent( Graphics g ) {

}
public void paint(Graphics g) {

    super.paint(g);
    Graphics2D square = (Graphics2D) g;
    Graphics2D triangle = (Graphics2D) g;
    Graphics2D circle = (Graphics2D) g;

    square.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    square.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    square.setColor(new Color(0, 0, 200));
    square.fill(myRect);

    triangle.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    triangle.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    triangle.setColor(new Color(139, 89, 255));
    triangle.fill(myTr);

    circle.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    circle.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    circle.setColor(new Color(0, 0, 117));
    circle.fill(myCr);
}

class MovingAdapter extends MouseAdapter {

    private int x;
    private int y;

    public void mousePressed(MouseEvent e) {
        x = e.getX();
        y = e.getY();
    }

    public void mouseDragged(MouseEvent e) {
        int dx = e.getX() - x;
        int dy = e.getY() - y;

        if (myRect.contains(x, y)) {
            myRect.x += dx;
            myRect.y += dy;
            repaint();
        }

        else if (myTr.contains(x, y)) {
          myTr.translate(dx, dy);
            repaint();
       }
        else if (myCr.contains(x, y)) {
            myCr.x += dx;
            myCr.y += dy;
            repaint();
        }
        x += dx;
        y += dy;
    }
    }



    public static void main(String[] args) {
    JFrame frame = new JFrame("Shapes World");
    MouseMoveScale m = new MouseMoveScale();
    m.setDoubleBuffered(true);
    frame.add(m);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(300, 300);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
   }
   }

Suggestions:

  1. Put all the shapes into a List<Shape>
  2. Iterate through the list forward in the paintComponent, drawing each shape. The last one drawn will be on top.
  3. In the mouse listener/adapter, iterate through the shapes list backwards to find out which shape was pressed, and exit the loop as soon as any shape has been found. Do this backwards so that the one on top gets checked first.
  4. When a shape is found, remove it from the list, and then re-add it and call repaint() . This will have it drawn on the top.

For example:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;

@SuppressWarnings("serial")
public class DragShapes extends JPanel {
    private static final Color Background = Color.WHITE;
    private int panelWidth;
    private int panelHeight;
    private List<ColorShape> shapes = new ArrayList<>();

    public DragShapes(int width, int height, int diskCount) {
        this.panelWidth = width;
        this.panelHeight = height;
        setBackground(Background);

        MyMouse myMouse = new MyMouse();
        addMouseListener(myMouse);
        addMouseMotionListener(myMouse);

        double satVariance = 0.4;
        for (int i = 0; i < diskCount; i++) {           
            // create some semi-random colors
            float hue = ((float) i) / (float) diskCount;
            float brightness = (float) (satVariance * Math.random() + 1 - satVariance);
            float saturation = (float) (satVariance * Math.random() + 1 - satVariance);
            Color color = Color.getHSBColor(hue, saturation, brightness);

            // create random placement
            int x = (int) (Math.random() * (width - ColorShape.WIDTH) + ColorShape.WIDTH / 2);
            int y = (int) (Math.random() * (height - ColorShape.WIDTH) + ColorShape.WIDTH / 2);

            // create random Color Shapes using the above locations and colors
            shapes.add(new ColorShape(color, x, y));
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        // do JPanel house-keeping painting
        super.paintComponent(g);

        // create smooth curves
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        // iterate through the shapes list, drawing each shape
        for (ColorShape colorShape : shapes) {
            colorShape.draw(g2);
        }
    }

    // size the JPanel appropriately
    @Override
    public Dimension getPreferredSize() {
        Dimension prefSize = super.getPreferredSize();
        if (isPreferredSizeSet()) {
            return prefSize;
        }
        int w = Math.max(prefSize.width, panelWidth);
        int h = Math.max(prefSize.height, panelHeight);
        return new Dimension(w, h);
    }

    // combination mouse listener and mouse motion listener
    private class MyMouse extends MouseAdapter {
        private ColorShape colorShape; // the current color shape that we're dragging
        private Point p; // previous location of the color shape

        @Override
        public void mousePressed(MouseEvent e) {
            // iterate *backward* through the list
            for (int i = shapes.size() - 1; i >= 0; i--) {
                // get the shape in the list
                ColorShape colorShape = shapes.get(i);
                // if it contains the current point, we've got it!
                if (colorShape.contains(e.getPoint())) {
                    // set the mouse adapter colorShape field with this shape
                    this.colorShape = colorShape;
                    // set the current point, p
                    this.p = e.getPoint();

                    // *remove* the shape from the list
                    shapes.remove(colorShape);

                    // re-add it so it is now the last shape in the list
                    shapes.add(colorShape);

                    // draw all shapes
                    repaint();
                    return;  // we're done
                }
            }
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            moveShape(e); // move the dragged shape
            colorShape = null;  // and release the reference to it
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            moveShape(e); // move the dragged shape
        }

        private void moveShape(MouseEvent e) {
            // if we are not currently dragging a shape
            if (colorShape == null) {
                return;  // get out of here
            }

            // otherwise translate this shape using the 2 points
            colorShape.translate(p, e.getPoint());          
            repaint();

            // re-set the current point
            p = e.getPoint();
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            int width = 1000;
            int height = 800;
            int diskCount = 40;
            JFrame frame = new JFrame("Drag Shapes");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(new DragShapes(width, height, diskCount));
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
    }
}
class ColorShape {
    public static final int WIDTH = 100;
    private Color color;
    private int x;
    private int y;

    // path 2d objects are Shape objects that can be translated
    // easily using an affine transform
    private Path2D path;

    public ColorShape(Color color, int x, int y) {
        super();
        this.color = color;
        this.x = x;
        this.y = y;

        // create an ellipse (circle) and make a Path2D object with it
        Shape shape = new Ellipse2D.Double(x - WIDTH / 2, y - WIDTH / 2, WIDTH, WIDTH);
        path = new Path2D.Double(shape);
    }

    // test if the point is contained by this shape
    public boolean contains(Point p) {
        return path.contains(p);
    }

    // draw our shape
    public void draw(Graphics2D g2) {
        g2.setColor(color);
        g2.fill(path);
        g2.setColor(Color.BLACK);
        g2.draw(path);
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public static int getWidth() {
        return WIDTH;
    }

    public Color getColor() {
        return color;
    }

    // the magic of affine transforms 
    public void translate(Point p0, Point p1) {
        int tx = p1.x - p0.x;
        int ty = p1.y - p0.y;
        path.transform(AffineTransform.getTranslateInstance(tx, ty));
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM