创建在插入每个点后更新的多边形

Create Polygon that update after the insertion of every point

我在学校项目中遇到问题,我在其中创建了一个多边形,当我插入点时,多边形会在插入每个点后更新。

例如

我的程序:

我想要的结果:

我的理解是,为了让它看起来像结果,删除 Point3 和 Point1 之间的 link,新的将在 Point4 和 Point1 之间。如果这是解决方案,我不知道要在我的代码中添加什么来修复它。

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

public class ShapesByMouseDrag3 extends JFrame {

    private static final int FW = 800;
    private static final int FH = 600;

    private Point p1;
    private Point p2;

    private int x;
    private int y;

    ArrayList<Integer> alX = new ArrayList<>();
    ArrayList<Integer> alY = new ArrayList<>();

    JRadioButton lineRB = new JRadioButton("Line");
    JRadioButton rectRB = new JRadioButton("Rectangle");
    JRadioButton Ellipse = new JRadioButton("Ellipse");
    JRadioButton PolygonRB = new JRadioButton("Polygon");

    public static void main(String[] args) {
        new ShapesByMouseDrag3();
    }

    public ShapesByMouseDrag3() {
        setSize(FW, FH);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("Draw Graphics Objects by Mouse Drag");
        setLocationRelativeTo(null);

        setLayout(new BorderLayout());

        PaintPanel paintPanelObj = new PaintPanel(FW, FH);

        JPanel chooseShapePanel = new JPanel();
        chooseShapePanel.setBackground(Color.WHITE);
        chooseShapePanel.setLayout(new GridLayout(4, 1));

        chooseShapePanel.setBorder(BorderFactory.createTitledBorder(
                BorderFactory.createEtchedBorder(), "Shapes"));

        //Create the radio buttons.
        //Create a button group and add buttons
        ButtonGroup bgroup = new ButtonGroup();
        bgroup.add(lineRB);
        bgroup.add(rectRB);
        bgroup.add(Ellipse);
        bgroup.add(PolygonRB);

        // add buttons to chooseShapePanel panel
        chooseShapePanel.add(lineRB);
        chooseShapePanel.add(rectRB);
        chooseShapePanel.add(Ellipse);
        chooseShapePanel.add(PolygonRB);
        add(paintPanelObj, BorderLayout.CENTER);
        add(chooseShapePanel, BorderLayout.WEST);
        setVisible(true);
        pack();
    }

    private class PaintPanel extends JPanel {

        private int PW; // panel-width
        private int PH; // panel-height

        Collection<Shape> shapeList = new ArrayList<Shape>();
        Collection<Shape> shapeListR = new ArrayList<Shape>();

        public PaintPanel(int W, int H) {
            PW = W;
            PH = H;
            setPreferredSize(new Dimension(PW, PH)); // set width & height of panel 
            setBorder(BorderFactory.createTitledBorder(
                    BorderFactory.createEtchedBorder(), "Canvas"));

            addMouseListener(new MouseClickListener());
        }

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

            g2.setStroke(new BasicStroke(2f));
            g2.setColor(Color.blue);

            if (lineRB.isSelected()) {
                makeLine();
            } else if (rectRB.isSelected()) {
                makeRectangle();
            } else if (Ellipse.isSelected()) {
                makeEllipse();
            } else if (PolygonRB.isSelected()) {
                makePolygon();
            }

            // draw all the shapes stored in the collection
            Iterator itr = shapeList.iterator();
            while (itr.hasNext()) {
                g2.draw((Shape) itr.next());
            }

            // reset
            p1 = null;
            p2 = null;

        }

        public void makeLine() {
            if (p1 != null && p2 != null) {
                shapeList.add(new Line2D.Double(p1.x, p1.y, p2.x, p2.y));
            }
        }

        public void makeRectangle() {
            double RectangleX = Math.min(p1.x, p2.x);
            double RectangleY = Math.min(p1.y, p2.y);
            double RectangleW = Math.abs(p1.x - p2.x);
            double RectangleH = Math.abs(p1.y - p2.y);
            if (p1 != null && p2 != null) {
                shapeList.add(new Rectangle2D.Double(RectangleX, RectangleY, RectangleW, RectangleH));
            }
        }

        public void makeEllipse() {
            double EllipseX = Math.min(p1.x, p2.x);
            double EllipseY = Math.min(p1.y, p2.y);
            double EllipseW = Math.abs(p1.x - p2.x);
            double EllipseH = Math.abs(p1.y - p2.y);
            if (p1 != null && p2 != null) {
                shapeList.add(new Ellipse2D.Double(EllipseX, EllipseY, EllipseW, EllipseH));
            }
        }

        public void makePolygon() {

            int[] xArray = new int[alX.size()];
            int[] yArray = new int[alY.size()];
            for (int i = 0; i < alX.size(); i++) {
                xArray[i] = alX.get(i);
                yArray[i] = alY.get(i);

            }
            if (p1 != null && p2 != null) {
                shapeList.add(new Polygon(xArray, yArray, xArray.length));
            }

        }

        private class MouseClickListener extends MouseAdapter {

            public void mousePressed(MouseEvent event) {
                p1 = new Point(event.getX(), event.getY());
                alX.add(p1.x);
                alY.add(p1.y);
            }

            public void mouseEntered(MouseEvent event) {
                alX.clear();
                alY.clear();
            }

            public void mouseReleased(MouseEvent event) {
                p2 = new Point(event.getX(), event.getY());
                alX.add(p2.x);
                alY.add(p2.y);
                repaint();
            }
        }
    }
}

不要使用 paintComponent 来构建形状,这不是 paintComponent 的用途。

我会使用 Path2D(优于 Polygon),因为您可以更轻松地向 Path2D 添加新点。

下面是一个简单的例子,它使用两个Path2D实例来跟踪形状。第一个是我们不断添加点的“开放”路径,第二个是第一个的“封闭”副本。这是故意的,就好像你在每次点击后关闭形状,它只会绘制从第一个点击点延伸的线。

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.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private Path2D polygon = null;
        // Give some guidence
        private Point lastClickPoint = null;
        private Point currentMousePoint = null;

        public TestPane() {
            MouseAdapter ma = new MouseAdapter() {
                // This is the "acutal" shape been draw
                // This allows us to "close" the polygon
                // without it breaking the underlying shape
                private Path2D mouseShape = null;

                @Override
                public void mouseClicked(MouseEvent e) {
                    if (mouseShape == null) {
                        mouseShape = new Path2D.Double();
                        mouseShape.moveTo(e.getX(), e.getY());
                    } else {
                        mouseShape.lineTo(e.getX(), e.getY());
                    }
                    polygon = new Path2D.Double();
                    polygon.append(mouseShape, true);
                    polygon.closePath();
                    lastClickPoint = e.getPoint();
                    repaint();
                }

                @Override
                public void mouseMoved(MouseEvent e) {
                    currentMousePoint = e.getPoint();
                    repaint();
                }
            };

            addMouseListener(ma);
            addMouseMotionListener(ma);
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(Color.BLACK);
            if (polygon != null) {
                g2d.draw(polygon);
            }
            if (lastClickPoint != null && currentMousePoint != null) {
                g2d.setColor(Color.GRAY);
                g2d.draw(new Line2D.Double(lastClickPoint, currentMousePoint));
            }
            g2d.dispose();
        }

    }
}

这是一个重点示例,仅解决一个问题,您将需要修改代码以适应它。我会在每次单击鼠标时确定您要创建的形状类型,并创建一个可以绘制的“中间”形状,直到用户“提交”更改,届时将添加形状List,但这就是我