Reputation: 25
I wanna draw a polygon and then fill it. My code looks like this:
@Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
if (polygons.isEmpty()) {
return;
}
for (int j = 0; j < polygons.size(); j++) {
ArrayList<Point> ActPoint = polygons.get(j);
if (ActPoint.isEmpty()) {
return;
}
Point a = new Point();
a = ActPoint.get(0);
for (int p = 0; p < ActPoint.size(); p++) {
Point b = ActPoint.get(p);
Line2D.Double line = new Line2D.Double(a, b);
g2d.draw(line);
a = b;
}
}
for (int j = 0; j < polygons.size(); j++) {
ArrayList<Integer> listX = new ArrayList<>();
ArrayList<Integer> listY = new ArrayList<>();
for (int p = 0; p < polygons.get(j).size(); p++) {
listX.add(polygons.get(j).get(p).x );
listY.add(polygons.get(j).get(p).y );
}
g.fillPolygon(convertIntegers(listX),convertIntegers (listY), polygons.get(j).size());
}
}
I don't know how too make the code so it fills the polygon only after i finished drawing it. Like if i wanna have a polygon with 5 sides, the polygon is filled only after i finished drawing all the sides. Also i'd like the polygon to be filled only when i action a button. I tried to make a function
public void fill (Graphics g){
for (int j = 0; j < polygons.size(); j++) {
ArrayList<Integer> listX = new ArrayList<>();
ArrayList<Integer> listY = new ArrayList<>();
for (int p = 0; p < polygons.get(j).size(); p++) {
listX.add(polygons.get(j).get(p).x );
listY.add(polygons.get(j).get(p).y );
}
g.fillPolygon(convertIntegers(listX),convertIntegers (listY), polygons.get(j).size());
}
and i tried to call it here
if (e.getActionCommand().equals("Fill")) {
}
but i don't really know how. Please help.
P.S. Is there other ways to fill a polygon without the fillPolygon function?
Upvotes: 0
Views: 2221
Reputation: 1168
UPDATE: added Timer-based renderer to display the lines one at a time at the end of this answer.
Firstly, I recommend @Overriding paintComponent()
, instead of paint()
.
Secondly, to draw a Polygon
then fill a Polygon
, you literally just stack the commands as the Graphics
context will paint in order.
for(int j = 0; j < polygons.size(); j++) {
ArrayList<Integer> listX = new ArrayList<>();
ArrayList<Integer> listY = new ArrayList<>();
for (int p = 0; p < polygons.get(j).size(); p++) {
listX.add(polygons.get(j).get(p).x);
listY.add(polygons.get(j).get(p).y);
}
// this may need slight conversion depending on parameters required
g.drawPolygon(convertIntegers(listX), convertIntegers(listY), polygons.get(j).size());
g.fillPolygon(convertIntegers(listX), convertIntegers(listY), polygons.get(j).size());
}
If you override paintComponent()
for your chosen object (I usually use a JPanel
for custom painting) all you then have to do is call repaint() to refresh the view (not that you should need in this instance).
To recap, override paintComponent()
on a JPanel
, stack your drawPolygon
/ fillPolygon
calls and if you want to control when your polygon is displayed, handle that by adding / removing the JPanel
as necessary from your application. Or set a boolean
flag that indicates "toBeDrawn" or not and modify your paintComponent
code so that it only draws the polygons when this is set to true.
UPDATE: example runnable class below demonstrated Timer-based drawLine()
functionality.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Test extends JPanel {
private static final long serialVersionUID = 1L;
private Timer lineTimer;
private Polygon toBeFilled;
private ArrayList<Point[]> inactiveLines;
private ArrayList<Point[]> activeLines;
private boolean toBeDrawn = false;
public static void main(String[] args) {
JFrame frame = new JFrame("Test");
frame.getContentPane().setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
Test test = new Test();
frame.add(test);
frame.pack();
frame.setVisible(true);
test.getLineTimer().start();
}
public Test() {
super();
setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
setPreferredSize(new Dimension(480, 340));
setBackground(Color.BLACK);
int midpointX = getPreferredSize().width / 2;
int midpointY = getPreferredSize().height / 2;
int lineWidth = 20;
// let's make a square
toBeFilled = new Polygon();
// let's centre this square nicely
toBeFilled.addPoint(midpointX - (lineWidth / 2), midpointY - (lineWidth / 2)); // top-left
toBeFilled.addPoint(midpointX + (lineWidth / 2), midpointY - (lineWidth / 2)); // top-right
toBeFilled.addPoint(midpointX + (lineWidth / 2), midpointY + (lineWidth / 2)); // bottom-right
toBeFilled.addPoint(midpointX - (lineWidth / 2), midpointY + (lineWidth / 2)); // bottom-left
inactiveLines = new ArrayList<Point[]>();
activeLines = new ArrayList<Point[]>();
for(int n = 0; n < 4; n++) {
Point[] points = new Point[2];
if(n < 3) {
points[0] = new Point(toBeFilled.xpoints[n], toBeFilled.ypoints[n]);
points[1] = new Point(toBeFilled.xpoints[n + 1], toBeFilled.ypoints[n + 1]);
} else {
// loop back to the first point in the array
points[0] = new Point(toBeFilled.xpoints[n], toBeFilled.ypoints[n]);
points[1] = new Point(toBeFilled.xpoints[0], toBeFilled.ypoints[0]);
}
inactiveLines.add(points);
}
ActionListener lineAction = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(inactiveLines.get(inactiveLines.size() - 1) != null) {
int count = 0;
for(Point[] pArray : inactiveLines) {
if(pArray != null) {
activeLines.add(new Point[] { pArray[0], pArray[1] });
inactiveLines.set(count, null);
repaint();
break;
}
count++;
}
} else {
// we've exhausted the line array, so now it's time to fill it
toBeDrawn = true;
lineTimer.stop();
repaint();
}
}
};
lineTimer = new Timer(1000, lineAction);
}
@Override
public void paintComponent(Graphics g) {
// useful for animation
Toolkit.getDefaultToolkit().sync();
super.paintComponent(g);
if(toBeDrawn) {
doFillPainting(g);
} else {
doLinePainting(g);
}
}
private void doFillPainting(Graphics g) {
// Graphics2D is more advanced than the older Graphics API, and more reliable
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.WHITE);
if(toBeFilled != null) {
g2d.fillPolygon(toBeFilled);
}
}
private void doLinePainting(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.WHITE);
for(Point[] activeLine : activeLines) {
g2d.drawLine(activeLine[0].x, activeLine[0].y, activeLine[1].x, activeLine[1].y);
}
}
public Timer getLineTimer() {
return lineTimer;
}
public void setLineTimer(Timer lineTimer) {
this.lineTimer = lineTimer;
}
public Polygon getToBeFilled() {
return toBeFilled;
}
public void setToBeFilled(Polygon toBeFilled) {
this.toBeFilled = toBeFilled;
}
public boolean isToBeDrawn() {
return toBeDrawn;
}
public void setToBeDrawn(boolean toBeDrawn) {
this.toBeDrawn = toBeDrawn;
}
}
Upvotes: 1