I am having a problem with a school project in Which I create a Polygon that when I insert points the polygon update after the insertion of every point.
For example
My program:
The result I want:
What I understood is that to make it look like the result, remove the link between Point3 and Point1 and the new one will be between Point4 and Point1. If this is the solution I don't know what to add to my code to fix it.
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();
}
}
}
}
CodePudding user response:
Don't use paintComponent
to build the shapes, this is not what paintComponent
is for.
I would use Path2D
(over Polygon
) as you add new points to Path2D
in a much easier way.
The following is a simple example, it uses two Path2D
instances to track the shape. The first is an "open" path, which we keep adding points to, the second is a "closed" copy of the first. This is intentional, as if you close the shape after each click, it will just draw lines extending from the first click point.
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();
}
}
}
This is focused example, solving just the one problem and you're going to need to modify you code to fit it. I would, on each mouse click, be making determinations about what type of shape you are trying to create and create a "intermediate", which can be painted, until the user "commits" the changes, at which time the shape would be added to the List
, but that's me