简体   繁体   English

如何将我用paintComponent绘制并用鼠标单击的形状带到前面?

[英]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?我可以将参数与 repaint() 一起传递以告诉程序例如必须最后绘制单击的圆,还是可以创建三种不同的绘制方法来跟踪绘制顺序?

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.另一个问题是我的 if 循环,它可以很好地将正方形拖动到圆形和三角形中,但是如果鼠标在同一区域,圆形和三角形也会跟着它们一起移动。 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>将所有形状放入一个List<Shape>
  2. Iterate through the list forward in the paintComponent, drawing each shape.在paintComponent 中向前遍历列表,绘制每个形状。 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() .找到形状后,将其从列表中删除,然后重新添加并调用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));
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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