java - 获取在 Jpanel 上绘制的 Path2D 形状的(起始)X 和 Y 坐标

标签 java swing graphics jpanel

所以,我有一个程序,我可以使用 Path2D 对象将形状添加到 JPanel,然后我可以单击并拖动它们。我想要做的是能够找到药物后形状的最终 X 和 Y 坐标。坐标必须是左上角坐标。有什么想法吗?

// add a circle to center of the screen
public void addCircle(int width, int height) {
    Path2D circ = new Path2D.Double();
    circ.append(new Ellipse2D.Double(getWidth() / 2 - width / 2,
            getHeight() / 2 - height / 2, width, height), true);
    shapes.add(circ);
    repaint();
}
            ..................
//paint all shapes
@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    this.setOpaque(true);
    this.setBackground(Color.WHITE);
    Graphics2D g2 = (Graphics2D) g;
    g2.setStroke(new BasicStroke(2));
    for (Path2D shape : shapes) {
        g2.draw(shape);
    }
}
            ..................
    // if the mouse click is in the circle, set pressed=true
    @Override
    public void mousePressed(MouseEvent e) {
        if (e.getButton() != MouseEvent.BUTTON1) {
            return;
        }
        for (int i = 0; i < shapes.size(); i++) {
            if (shapes.get(i) != null
                    && shapes.get(i).contains(e.getPoint())) {
                currentIndex = i;
                pressed = true;
                this.point = e.getPoint();
            }
        }
    }

    //if pressed=true, move circle with mouse
    @Override
    public void mouseDragged(MouseEvent e) {
        if (pressed && !lineSelected) {
            int deltaX = e.getX() - point.x;
            int deltaY = e.getY() - point.y;
            shapes.get(currentIndex).transform(
                    AffineTransform.getTranslateInstance(deltaX, deltaY));
            point = e.getPoint();
            //I need to find the new coordinates here!!!!!!!!!!!
            repaint();
        }
    }

完整代码

class Canvas extends JPanel {
private static final long serialVersionUID = 1L;

private List<Path2D> shapes = new ArrayList<Path2D>();
private int currentIndex;
private Point lineStartingPoint = new Point();
private Point lineEndingPoint = new Point();
private boolean drawing;
private boolean lineSelected;
private Path2D.Double linePath;
private Shapes myShapes = new Shapes();
private List<Path2D> circles = new ArrayList<Path2D>();

public Canvas() {
    MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
    addMouseListener(myMouseAdapter);
    addMouseMotionListener(myMouseAdapter);
}

public void setList(ArrayList<UMLCircle> shapes) {

}

public List<UMLCircle> getList() {
    return null;
}

public void addSquare(int width, int height) {
    Path2D rect2 = new Path2D.Double();
    rect2.append(new Rectangle(getWidth() / 2 - width / 2, getHeight() / 2
            - height / 2, width, height), true);

    shapes.add(rect2);
    repaint();
}

public void addLine() {
    lineSelected = true;
    repaint();
}

public void addCircle(int width, int height) {
    myShapes.addCircle(getWidth() / 2 - width / 2, getHeight() / 2 - height
            / 2, width, height);
    Path2D circ = new Path2D.Double();
    circ.append(new Ellipse2D.Double(getWidth() / 2 - width / 2,
            getHeight() / 2 - height / 2, width, height), true);
    circles.add(circ);
    shapes.add(circ);
    repaint();
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    this.setOpaque(true);
    this.setBackground(Color.WHITE);
    Graphics2D g2 = (Graphics2D) g;
    if (lineSelected) {
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setStroke(new BasicStroke(2));
        g2.drawLine(lineStartingPoint.x, lineStartingPoint.y,
                lineEndingPoint.x, lineEndingPoint.y);
    }
    g2.setStroke(new BasicStroke(2));
    for (Path2D shape : shapes) {
        g2.draw(shape);
    }
}

class MyMouseAdapter extends MouseAdapter {
    private boolean pressed = false;
    private Point point;

    @Override
    public void mousePressed(MouseEvent e) {
        if (e.getButton() != MouseEvent.BUTTON1) {
            return;
        }
        for (int i = 0; i < shapes.size(); i++) {
            if (shapes.get(i) != null
                    && shapes.get(i).contains(e.getPoint())) {
                currentIndex = i;
                pressed = true;
                this.point = e.getPoint();
            }
            if (circles.get(i) != null
                    && circles.get(i).contains(e.getPoint())) {
                currentIndex = i;
                pressed = true;
                this.point = e.getPoint();
            }
        }
        if (lineSelected) {
            drawing = true;
            lineStartingPoint = e.getPoint();
            lineEndingPoint = lineStartingPoint;
        }
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        if (pressed && !lineSelected) {
            int deltaX = e.getX() - point.x;
            int deltaY = e.getY() - point.y;
            shapes.get(currentIndex).transform(
                    AffineTransform.getTranslateInstance(deltaX, deltaY));
            point = e.getPoint();
            myShapes.updateCircleLocation(currentIndex, point.x, point.y);
            System.out.println(point.x + " " + point.y);
            repaint();
        }
        if (drawing) {
            lineEndingPoint = e.getPoint();
            repaint();
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        if (drawing && lineSelected) {
            drawing = false;
            lineSelected = false;
            lineEndingPoint = e.getPoint();
            linePath = new Path2D.Double();
            linePath.moveTo(lineStartingPoint.getX(),
                    lineStartingPoint.getY());
            linePath.lineTo(lineEndingPoint.getX(), lineEndingPoint.getY());
            shapes.add(linePath);
            repaint();
        }
        pressed = false;
    }
}
}

编辑

偏移量的计算:

            int deltaX = e.getX() - point.x;
            int deltaY = e.getY() - point.y;
            shapes.get(currentIndex).transform(
                    AffineTransform.getTranslateInstance(deltaX, deltaY));
            point = e.getPoint();
            int newXPos = e.getX() - deltaX; // final X pos
            int newXPos = e.getX() - deltaX; // final Y pos

最佳答案

在你做任何事情之前,你需要知道鼠标单击相对于形状角的偏移量,这将允许你拖动对象,这样它就不会突然“跳”到你当前的鼠标位置。 .

@Override
public void mousePressed(MouseEvent e) {
    //...
    for (Shape shape : myShapes) {
            //...
            this.point = e.getPoint();
            int deltaX = point.x - shape.getBounds().x;
            int deltaY = point.y - shape.getBounds().y;
            offset = new Point(deltaX, deltaY);
            //...
        }
    }
}

然后,您将计算当前鼠标位置和偏移量之间的变化增量。由于您要应用平移,因此还需要减去形状的当前位置,因为平移基于形状的当前位置,而我们只想应用更改量

@Override
public void mouseDragged(MouseEvent e) {
    if (pressed) {
        int index = myShapes.indexOf(clickedShape);
        myShapes.remove(index);

        int deltaX = e.getPoint().x - offset.x;
        int deltaY = e.getPoint().y - offset.y;

        clickedShape = new Path2D.Double(clickedShape,
                        AffineTransform.getTranslateInstance(
                                        deltaX - clickedShape.getBounds().x,
                                        deltaY - clickedShape.getBounds().y));
        myShapes.add(index, clickedShape);
        point = e.getPoint();
        repaint();
    }
}

现在,说了这么多,不要这样做......

protected void paintComponent(Graphics g) {
    //...
    this.setOpaque(true);
    this.setBackground(Color.WHITE);

从绘制方法中更改组件的状态可能会设置重绘请求的无限循环,这可能会阻塞您的系统。此外,您所做的更改不会应用于当前图形上下文,因为这些属性通常由 paint 方法应用...

还有工作副本......

import java.awt.BasicStroke;
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.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

class Canvas extends JPanel {

    private static final long serialVersionUID = 1L;

    private boolean drawing;
    private List<Shape> myShapes = new ArrayList<Shape>();

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

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

    public Canvas() {
        MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
        addMouseListener(myMouseAdapter);
        addMouseMotionListener(myMouseAdapter);
        addSquare(100, 100);
    }

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

    public void setList(ArrayList<Shape> shapes) {

    }

    public List<Shape> getList() {
        return null;
    }

    public void addSquare(int width, int height) {
        Path2D rect2 = new Path2D.Double();
        rect2.append(new Rectangle(getWidth() / 2 - width / 2, getHeight() / 2
                        - height / 2, width, height), true);

        myShapes.add(rect2);
        repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setStroke(new BasicStroke(2));
        for (Shape shape : myShapes) {
            g2.draw(shape);
        }
    }

    class MyMouseAdapter extends MouseAdapter {

        private boolean pressed = false;
        private Point point;
        private Point offset;
        private Shape clickedShape;

        @Override
        public void mousePressed(MouseEvent e) {
            if (e.getButton() != MouseEvent.BUTTON1) {
                return;
            }
            for (Shape shape : myShapes) {
                if (shape != null
                                && shape.contains(e.getPoint())) {
                    System.out.println("Clicked");
                    pressed = true;
                    clickedShape = shape;
                    this.point = e.getPoint();
                    int deltaX = point.x - shape.getBounds().x;
                    int deltaY = point.y - shape.getBounds().y;
                    offset = new Point(deltaX, deltaY);
                    System.out.println(point + "x" + offset);
                    repaint();
                    break;
                }
            }
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            if (pressed) {
                int index = myShapes.indexOf(clickedShape);
                myShapes.remove(index);

                int deltaX = e.getPoint().x - offset.x;
                int deltaY = e.getPoint().y - offset.y;

                clickedShape = new Path2D.Double(clickedShape,
                                AffineTransform.getTranslateInstance(
                                                deltaX - clickedShape.getBounds().x,
                                                deltaY - clickedShape.getBounds().y));
                myShapes.add(index, clickedShape);
                point = e.getPoint();
                repaint();
            }
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            offset = null;
            pressed = false;
        }
    }
}

关于java - 获取在 Jpanel 上绘制的 Path2D 形状的(起始)X 和 Y 坐标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26108351/

相关文章:

java - 尝试使用 JFrame 和 JPanel 将窗口绘制为黑色

windows - 获取图形或显存的API

algorithm - 绘制别名、像素完美的 1px 样条曲线(特别是 Catmull-Rom)

java - Java游戏编程

java - 如何使用 Spring Security 以编程方式验证 `User` 并使用我的 `UserDetailsServie` 实现?

java - 是否适合该声明。 if (0 != expression or variable) {} 在 java 中?

java - 没有布局管理器的响应式 JFrame

java - JFreeChart 中的多线程

Java序列化-Android反序列化

java - ForEach 循环中断和连接线程