Home > Blockchain >  How do I connect the dots to get a polygon in JAVA?
How do I connect the dots to get a polygon in JAVA?

Time:10-11

I'm making an application for creating convex polygon.

I imagined it to be so that I first set the vertices of the polygon and then create it.

I was able to make the addition of points (vertices). Now I need help connecting the dots with a line.

This is what it looks like: Start

Here's the GUI with four points

Points

Here's the GUI with a polygon

Polygon

I'm not showing it, but the Reset button clears the drawing area.

Explanation

When I create a Swing GUI, I use the model-view-controller pattern. This pattern allows me to separate my concerns and focus on one part of the Swing application at a time.

A Swing application model consists of one or more plain Java getter/setter classes.

A Swing view consists of a JFrame and one or more JPanels.

Swing controllers are the listeners that are attached to JButtons and drawing JPanels.

Model

For this application, I created a PolygonModel class. The class holds a boolean that tells me whether or not to draw the polygon and a java.util.List of java.awt.Point instances. The Point class holds an X and Y int value.

View

All Swing applications must start with a call to the SwingUtilities invokeLater method. This method ensures that the Swing components are created and executed on the Event Dispatch Thread.

I broke up your main method into a couple of methods. I separate the creation of the JFrame from the creation of the JPanels. This allows me to separate my concerns and focus on one part of the GUI at a time.

The JFrame methods must be called in a specific order. This is the order I use for most of my Swing applications.

I changed your PadDraw class to extend a JPanel. I moved the MouseAdapter code to its own class. Your drawing panel should draw. Period. Nothing else.

The paintComponent method always starts with a call to the super.paintComponent method. This maintains the Swing paint chain and helps to eliminate unwanted drawing artifacts.

The drawing JPanel is cleared before every repaint. Therefore, you have to completely redraw your image each time. That's why we store the List of Point instances in the model.

Controller

I created three controller classes.

The PointListener class extends MouseAdapter. Notice how simple the mousePressed method becomes with an application model.

The two JButtons each have their own ActionListener. Since they are so simple, I made each of them lambdas.

Code

Here's the complete runnable code. I made all the additional classes inner classes so I could make them public and post the code as one block.

import java.awt.BasicStroke;
import java.awt.BorderLayout;
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.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EtchedBorder;

public class PolygonImage implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new PolygonImage());
    }

    private final PolygonModel model;

    private final PadDraw drawPad;

    public PolygonImage() {
        this.model = new PolygonModel();
        this.drawPad = new PadDraw(this, model);
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("Draw Polygon");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(drawPad, BorderLayout.CENTER);
        frame.add(createButtonPanel(), BorderLayout.SOUTH);

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private JPanel createButtonPanel() {
        JPanel buttonPanel = new JPanel();
        buttonPanel
                .setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));

        JButton buttonDrawPolygon = new JButton("Draw Polygon");
        buttonDrawPolygon.addActionListener(event -> {
            model.setConnectPoints(true);
            repaint();
        });
        buttonPanel.add(buttonDrawPolygon);

        JButton buttonReset = new JButton("Reset");
        buttonReset.addActionListener(event -> {
            model.setConnectPoints(false);
            model.clearList();
            repaint();
        });
        buttonPanel.add(buttonReset);

        return buttonPanel;
    }

    public void repaint() {
        drawPad.repaint();
    }

    public class PadDraw extends JPanel {

        private static final long serialVersionUID = 1L;

        private final PolygonModel model;

        public PadDraw(PolygonImage view, PolygonModel model) {
            this.model = model;
            this.addMouseListener(new PointListener(view, model));
            this.setPreferredSize(new Dimension(450, 300));
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;

            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setColor(Color.black);

            // Draw points
            for (Point p : model.getPoints()) {
                int radius = 6;
                int diameter = radius   radius;
                g2d.fillOval(p.x - radius, p.y - radius, diameter, diameter);
            }

            // Draw polygon
            if (model.isConnectPoints()) {
                g2d.setStroke(new BasicStroke(5));
                List<Point> points = model.getPoints();
                if (points.size() >= 1) {
                    Point old = points.get(0);
                    for (int index = 1; index < points.size(); index  ) {
                        Point p = points.get(index);
                        g2d.drawLine(old.x, old.y, p.x, p.y);
                        old = p;
                    }
                    Point p = points.get(0);
                    g2d.drawLine(p.x, p.y, old.x, old.y);
                }
            }
        }

    }

    public class PointListener extends MouseAdapter {

        private final PolygonImage view;

        private final PolygonModel model;

        public PointListener(PolygonImage view, PolygonModel model) {
            this.view = view;
            this.model = model;
        }

        @Override
        public void mousePressed(MouseEvent event) {
            model.addPoint(event.getPoint());
            view.repaint();
        }
    }

    public class PolygonModel {

        private boolean connectPoints;

        private final List<Point> points;

        public PolygonModel() {
            this.points = new ArrayList<>();
            this.connectPoints = false;
        }

        public void setConnectPoints(boolean connectPoints) {
            this.connectPoints = connectPoints;
        }

        public boolean isConnectPoints() {
            return connectPoints;
        }

        public void clearList() {
            this.points.clear();
        }

        public void addPoint(Point point) {
            this.points.add(point);
        }

        public List<Point> getPoints() {
            return points;
        }

    }

}
  • Related