I have a simple elevator simulator. The painting class of that simulator, paints a wall on the left side and a wall on the right - both are Line2D Objects. In the center is a rectangle that represents the cabin.
My Member Variables are:
private PaintableElevator paintableObject;
private Line2D wallLeftSide = new Line2D.Double();
private Line2D wallRightSide = new Line2D.Double();
private Rectangle2D elevator = new Rectangle2D.Double();
paintableObject gives the information where to paint as proportions. For example, if it says that the cabin has a height of 0.1, than its height on the panel is: this.getHeight * 0.1
I also have a component Listener that just reacts on rezize Events as follows:
#Override
public void componentResized (ComponentEvent e)
{
wallLeftSide.setLine(new Point2D.Double(0, changeYCoordsOrigin(getHeight() * paintableObject.getTotalHeight())), new Point2D.Double(0, getWidth()));
wallRightSide.setLine(new Point2D.Double(getWidth(), changeYCoordsOrigin(getHeight() * paintableObject.getTotalHeight())), new Point2D.Double(getWidth(), getHeight()));
elevator.setRect(0, changeYCoordsOrigin(getHeight() * paintableObject.getHeightInShaft()), getWidth(), paintableObject.getCabinHeight() * getHeight() *-1);
}
My Problem is that Graphics 2D sets the origin of their coords to the top left hand side. I would like it to have on the button left side. thats why i use my method changeYCoordOrigin()
public double changeYCoordsOrigin (double coord)
{
return getHeight() - coord;
}
My hope was that I could convert my coords by calculating them minus the current height. That worked. But when I want to set a negative height for the rectangle, my component dont show anything.
But this is very important, because I want to drive my little cabin by the following code:
#Override
public void setHeigth (double height)
{
elevator.setRect(0, getHeight() * height, getWidth(), paintableObject.getCabinHeight());
repaint();
}
When just dont use changeYCoordOrigin and use a positive height, my elevator drives down, when i want to drive up. Because of that it is important to change the origin of the coordinates, or simulate that.
My paint Method just paints that objects:
#Override
public void paint (Graphics g)
{
if (g instanceof Graphics2D)
{
Graphics2D g2 = (Graphics2D) g;
g2.draw(wallLeftSide);
g2.draw(wallRightSide);
g2.setBackground(Color.gray);
g2.draw(elevator);
}
}
Related
im trying to paint random (not yet) circles on a JPanel through click on a JMenu.
Im using a JTextField (and have to keep this) for some output.
Here is my Class:
class RandomDrawer extends JPanel implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
//double x = Math.random();
//double y = Math.random();
Random generator = new Random();
int x = generator.nextInt(100)+1;
int y = generator.nextInt(100)+1;
//System.out.printf("x = %d y = %d\n", x, y);
status.setText(String.format("rnd draw x: %d y: %d", x, y));
Graphics2D gg = (Graphics2D) canvas.getGraphics();
gg.setColor(Color.BLACK);
gg.drawOval(50, 50, 50, 50);
}
}
As long i let the line
status.setText(String.format("rnd draw x: %d y: %d", x, y));
stay in there i get nothing drawn. Without it i get my circle, im not sure what the problem is. I cant figure out why nothing is drawn.
Thanks a lot
EDIT:
Hello, i tried to understand the given informations.
Sadly I have to draw using the Graphics2D class, so i guess i can not draw using shapes. So i tried this, sadly it wont draw yet, can u give me some tips?
I tried to create a new class DrawShape, my thought was that i could keep track with those objects.
In my understanding there should be a drawn oval right now
gg.drawOval(100,100,100,100);
Thank you.
class DrawShape {
public DrawShape(String string) {
// TODO Auto-generated constructor stub
}
}
class RandomDrawer extends JPanel implements ActionListener {
/* (non-Javadoc)
* #see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
private List<DrawShape> shapes = new ArrayList<DrawShape>();
public void addShape(DrawShape s) {
shapes.add(s);
repaint();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
final Graphics2D gg = (Graphics2D) g;
gg.setColor(Color.BLACK);
gg.drawOval(100, 100, 100, 100);
}
#Override
public void actionPerformed(ActionEvent e) {
Random generator = new Random();
int x = generator.nextInt(100)+100;
int y = generator.nextInt(100)+100;
if (e.getActionCommand()==("Draw RandomCircle")) {
System.out.printf("x = %d y = %d\n", x, y);
status.setText(String.format("rnd draw x:%d y:%d ", x, y));
DrawShape circle = new DrawShape("Circle");
addShape(circle);
int count = shapes.size();
System.out.printf("objects in array: %d\n", count);
}
else if (e.getActionCommand()==("Draw RandomRectangle")) {
System.out.printf("x = %d y = %d\n", x, y);
//status.setText(String.format("rnd draw x: y: "));
//Graphics2D gg = (Graphics2D) canvas.getGraphics();
//gg.setColor(Color.BLACK);
//gg.drawRect(x, y, generator.nextInt(x), generator.nextInt(y));
}
}
}
Painting and such happens event-driven. If a a piece of a component needs to be redrawn its paintComponent method is called.
This means you need a component that nows how to draw by for instance:
public class DrawShape {
public final String text;
public final Color color;
public final Shape shape;
public DrawShape(String text, Color color, Shape shape) {
this.text = text;
this.color = color;
this.shape = shape;
}
}
public class CanvasWithShapes extends JPanel {
private List<DrawShape> shapes = new ArrayList<>();
public void addShape(DrawShape shape) {
shapes.add(shape);
}
#Override
public void paintComponent(Graphics g) {
final Graphics2D gg = (Graphics2D) g;
// Java 8: shapes.stream().forEach((shape) -> gg.draw(shape));
for (DrawShape drawShape : shapes) {
gg.setColor(drawShape.color);
gg.draw(drawShape.shape);
Rectangle bounds = shape.getBounds();
gg.drawString(shape.text, bounds.x+ 10, bounds.y + 20);
}
}
}
And then just add shapes to be redrawn a bit later.
Shape oval = ...;
c.add(oval);
c.repaint(50L); // A bit later
More detailed
A Shape has many implementations of interest like rectangle and oval.
Graphics2D can draw and fill a Shape. So in your case it would be ideal to add such a Shape. Maybe together with color and text. So I took your DrawShape class to hold these properties.
Random generator = new Random();
int x = generator.nextInt(100)+100;
int y = generator.nextInt(100)+100;
if (e.getActionCommand().equals("Draw RandomCircle")) {
System.out.printf("x = %d y = %d\n", x, y);
status.setText(String.format("rnd draw x:%d y:%d ", x, y));
int w = generator.nextInt(100) + 10;
int h = w;
Shape circle = new Ellipse2D.Double(x, y, w, h);
addShape(new DrawShape(text, Color.BLACK, circle));
int count = shapes.size();
System.out.printf("objects in array: %d\n", count);
} else if (e.getActionCommand().equals("Draw RandomRectangle")) {
System.out.printf("x = %d y = %d\n", x, y);
generator.nextInt(y));
int w = generator.nextInt(100) + 10;
int h = generator.nextInt(100) + 10;
Shape rect = Rectangle2D.Double(x, y, w, h)
addShape(new DrawShape(text, Color.BLACK, rect));
}
Graphics2D gg = (Graphics2D) canvas.getGraphics();
Don't use the getGraphics() method to do painting. The painting is temporary. It will be lost if you resize the frame for example.
Instead you need to override the paintComponent() method of your panel.
If you want to paint multiple objects then you need to keep track of each object. Check out Custom Painting Approaches for the two common ways to do this:
keep of List of Objects to paint and then iterate through the List each time the component is repainted.
paint the Object directly to a BufferedImage and then just paint the BufferedImage.
The example paints Rectangles. Basically you need a method like the addRectangle(...) method to add a new object to paint. So every time you click your button you add the new random shape.
Presumably, your problem arises from the setText() invocation modifying the Graphics object in some unexpected way. It is rarely appropriate to use getGraphics() in your own code. Instead, paint with the Graphics that is given to you.
Your approach is anyway flawed. If you manage to draw on a GUI component only once, as you are trying to do, then whatever you have drawn will disappear when the component is next repainted. Repainting can happen for a wide variety of reasons, many of them unrelated to the program's own behavior.
What you need to do is store some kind of data that the component's paintComponent() method will rely upon to do your custom painting every time. It follows that you will need to override the paintComponent() method of the component on which you want the circles to be drawn. For example, you might create a class that records all the needed drawing details for one circle, and give RandomDrawer a List of those objects as a member variable. The action listener manipulates that list appropriately and schedules a repainting, and paintComponent() is overridden to perform the actual painting.
This question already has an answer here:
Clear portion of graphics with underlying image
(1 answer)
Closed 7 years ago.
I'm in the process of making a 2D game in which a player roams around a maze.
I want to implement some sort of "darkness", even something as simple as a transparent shape around the player surrounded by black, like this:
The problem I've found using Swing is that, while this is possible, it means having to redraw everything, which produces an annoying "flickering" effect every time it happens. Is there a way to make some sort of overlay, or just a good way of doing this in general in Swing? I'm not very experienced with GUI/visual stuff right now so I'd like to stick with Swing if possible.
EDIT: This is my method to paint the background, i.e. the floor, walls and exit:
public final void paintBG(Graphics g){
g.setColor(Color.LIGHT_GRAY); // Screen background
g.fillRect(0, 0, getWidth(), getHeight());
// Draw the Walls of the maze
// scalex and y are for scaling images/walls within the maze since I let users specify how big they want the maze
for (int j = 0; j < this.height; j++, y += scaley) {
x = 20;
for (int i = 0; i < this.width; i++, x += scalex) {
if (!(maze[j][i].northwall.isBroken())) // If the north wall isn't broken
{
g.drawImage(walltile, x, y, scalex, scaley / 5, null); // Draw a wall there (image, xpos, ypos, width, height, observer)
}
if (!(maze[j][i].eastwall.isBroken())) // etc
{
g.drawImage(walltile, x + scalex, y, scalex / 5, scaley, null);
}
if (!(maze[j][i].southwall.isBroken())) {
g.drawImage(walltile, x, y + scaley, scalex, scaley / 5, null);
}
if (!(maze[j][i].westwall.isBroken())) {
g.drawImage(walltile, x, y, scalex / 5, scaley, null);
}
if ((j == mazeinfo.getTargetM()) && (i == mazeinfo.getTargetN())) {
// Draw the exit
g.drawImage(jeep, x + (scalex / 2), y + (scaley / 2), cx, cy, null);
g.setColor(Color.LIGHT_GRAY);
if (maze[j][i].northwall.isEdge()) {
// Paint over the edge creating a 'way out'
g.fillRect(x, y, scalex, scaley / 4);
} else if (maze[j][i].eastwall.isEdge()) {
g.fillRect(x + scalex, y, scalex / 4, scaley);
} else if (maze[j][i].southwall.isEdge()) {
g.fillRect(x, y + scaley, scalex, scaley / 4);
} else if (maze[j][i].westwall.isEdge()) {
g.fillRect(x, y, scalex / 4, scaley);
}
}
}
}
}
I then have "paintPlayer" and "paintEnemy" methods to paint those sprites each time they move. The background only gets painted once, at the start.
Possibilities:
You may be drawing directly in a top level window such as a JFrame. If so, don't draw in the paintComonent method of a JPanel so that you use the automatic double buffering availabe.
You may be reading in an image from within a painting method, and if so, don't. These methods must paint and paint only and must be blindingly fast.
You may not be using a BufferedImage in your painting method but creating an image de-novo, and if so, don't. Draw the BufferedImage using Graphics#drawImage(...).
Perhaps your animation code is off. You may be calling repaint() from within paint or paintComponent, something that should never be done.
And the possible guesses can go on and on...
Edit
Your code shows that you may be re-paint the maze with every painting iteration -- don't do this. Instead draw the above into a BufferedImage, and draw that image within your paintComponent method. Then change the BufferedImage if the walls structurally change.
Note that the maze's logical structure (the non-visual data that tells which wall is open, which is closed) should be part of your program's data, and not its code.
Here in an example of using a LayerUI from Oracle's Swing UI documentation. Just change the AlphaComposite constant to something darker.
The following is a LayerUI subclass that draws a translucent circle wherever the mouse moves inside a panel.
class SpotlightLayerUI extends LayerUI<JPanel> {
private boolean mActive;
private int mX, mY;
#Override
public void installUI(JComponent c) {
super.installUI(c);
JLayer jlayer = (JLayer)c;
jlayer.setLayerEventMask(
AWTEvent.MOUSE_EVENT_MASK |
AWTEvent.MOUSE_MOTION_EVENT_MASK
);
}
#Override
public void uninstallUI(JComponent c) {
JLayer jlayer = (JLayer)c;
jlayer.setLayerEventMask(0);
super.uninstallUI(c);
}
#Override
public void paint (Graphics g, JComponent c) {
Graphics2D g2 = (Graphics2D)g.create();
// Paint the view.
super.paint (g2, c);
if (mActive) {
// Create a radial gradient, transparent in the middle.
java.awt.geom.Point2D center = new java.awt.geom.Point2D.Float(mX, mY);
float radius = 72;
float[] dist = {0.0f, 1.0f};
Color[] colors = {new Color(0.0f, 0.0f, 0.0f, 0.0f), Color.BLACK};
RadialGradientPaint p =
new RadialGradientPaint(center, radius, dist, colors);
g2.setPaint(p);
g2.setComposite(AlphaComposite.getInstance(
AlphaComposite.SRC_OVER, .6f));
g2.fillRect(0, 0, c.getWidth(), c.getHeight());
}
g2.dispose();
}
#Override
protected void processMouseEvent(MouseEvent e, JLayer l) {
if (e.getID() == MouseEvent.MOUSE_ENTERED) mActive = true;
if (e.getID() == MouseEvent.MOUSE_EXITED) mActive = false;
l.repaint();
}
#Override
protected void processMouseMotionEvent(MouseEvent e, JLayer l) {
Point p = SwingUtilities.convertPoint(e.getComponent(), e.getPoint(), l);
mX = p.x;
mY = p.y;
l.repaint();
}
}
To keep the spotlight's center updated on your player, create an event for player movement and register the LayerUI to listen for updates. See the setLayerEventMask() example in the JLayer link below.
source: How to Decorate Components with the JLayer Class
I made a java paint application and I made a rainbow brush function; however, I want to make the randomized colors into a smooth gradient. It is currently just printing ovals of differently colors and you can notice each distinct oval. Is there a way to make it a gradient?
Paint Project - CLICK HERE TO SEE PROGRAM
My Rainbow Fuction:
public void rainbow() {
Random generator = new Random();
int r = generator.nextInt(256);
int g = generator.nextInt(256);
int b = generator.nextInt(256);
Color color = new Color(r, g, b);
g2.setPaint(color);
}
My Mouse Listeners:
public DrawArea() {
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
// save coord x,y when mouse is pressed
oldX = e.getX();
oldY = e.getY();
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
// coord x,y when drag mouse
currentX = e.getX();
currentY = e.getY();
if (g2 != null) {
// draw oval if g2 context not null
g2.drawOval(oldX, oldY, 40, 40);
g2.fillOval(oldX, oldY, 40, 40);
// refresh draw area to repaint
repaint();
// store current coords x,y as olds x,y
oldX = currentX;
oldY = currentY;
}
}
});
}
Paint Component:
public void paintComponent(Graphics g) {
if (image == null) {
image = createImage(getSize().width, getSize().height);
g2 = (Graphics2D) image.getGraphics();
clear();
}
// enable antialiasing
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.drawImage(image, 0, 0, null);
}
I presume you're calling your rainbow function every ticks, which is why you get the effect as such.
To create the illusion of having a gradient, the r,g,b values must be changing slow enough to have the desired effect.
One way you can do that is by storing the value you want to LERP (see: https://en.wikipedia.org/wiki/Linear_interpolation) to.
//declare a variable to store the destinated Color;
public Color colorToBeLerped = null;
public Color currentColor = null;
public Color originalColor = null;
public final float deltaFactor = 0.2;
public void rainbow() {
if(currentColor==null||currentColor.equals(colorToBeLerped)){
Random generator = new Random();
int r = generator.nextInt(256);
int g = generator.nextInt(256);
int b = generator.nextInt(256);
colorToBeLerped = new Color(r, g, b);
originalColor = colorToBeLerped;
}
if(currentColor==null){
currentColor=colorToBeLerped;
}else{
//using the Color constructor that accepts float arguments, divide 255
currentColor= new Color((colorToBeLerped.getRed()-originalColor.getRed()*deltaFactor)/255,
(colorToBeLerped.getGreen()-originalColor.getGreen()*deltaFactor)/255,
(colorToBeLerped.getBlue()-originalColor.getBlue()*deltaFactor)/255);
}
g2.setPaint(currentColor);
}
Explaination:
1.Keep track of the color you want to lerp to, the current color you are in and the original color when the randomize function is called.
2.When we the first time rainbow function is called, current color will be set to the randomized color.
3.For every tick, if the current Color is not the destination color, we will increment by 1/5 of how much the difference is between original Color and destination Color.
4.A constant delta factor of 0.2 means that we will need 5 ticks to get from one color to another color, the lesser this variable is, the longer it will get from your original color to the destination color.
5.If we have reached the color, we will elect another new destination color.
*Not tested but I think you can figure out the rest
I've been working on this project for last week and can't figure out how to fix it. I feel like I'm so close but can't spot my error!
My assignment calls for me to draw circles along an imaginary line using the Java Graphics class. Draw a circle in the center with a radius of n. Then draw two circles with radius of n/2 whose endpoints intersect with the left and right arc of the circle.
I have been able to draw the 2nd step of two circles to the right and left of the first circle. However, my program is supposed to then draw four circles of the same size recursively. One circle to both the right and left side of the left circle AND one circle to both the right and left side of the right circle. Something is suspect with my code.
Any help would be greatly appreciated.
package fractalcircles;
import java.awt.*;
import javax.swing.*;
public class FractalCircles {
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{ //create a MyCanvas object
MyCanvas canvas1 = new MyCanvas();
//set up a JFrame to hold the canvas
JFrame frame = new JFrame();
frame.setTitle("FractalCircles.java");
frame.setSize(500,500);
frame.setLocation(100,100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//add the canvas to the frame as a content panel
frame.getContentPane().add(canvas1);
frame.setVisible(true);
}//end main
}//end class
class MyCanvas extends Canvas
{
public MyCanvas()
{} //end MyCanvas() constructor
//this method will draw the initial circle and invisible line
public void paint (Graphics graphics)
{
int x1,x2,y1,y2; //future x and y coordinates
int radius=125; //radius of first circle
int xMid=250, yMid=250; //center point (x,y) of circle
//draw invisible line
graphics.drawLine(0,250,500,250);
//draw first circle
graphics.drawOval(xMid-radius,yMid-radius,radius*2,radius*2);
//run fractal algorithm to draw 2 circles to the left and right
drawCircles(graphics, xMid, yMid, radius);
}
void drawCircles (Graphics graphics, int xMid, int yMid, int radius)
{
//used to position left and right circles
int x1 = xMid-radius-(radius/2);
int y1 = yMid-(radius/2);
int x2 = xMid+radius-(radius/2);
int y2= yMid-(radius/2);
if (radius > 5)
{
//draw circle to the left
graphics.drawOval(x1, y1, (radius/2)*2, (radius/2)*2);
//draw circle to the right
graphics.drawOval(x2, y2, (radius/2)*2, (radius/2)*2);
}
drawCircles (graphics, xMid, yMid, radius/2);
}
Some adapted version using recursion...
Draw the circle, then draw its 2 children by calling the same function again.
void drawCircles(Graphics graphics, int xMid, int yMid, int radius) {
// end recursion
if(radius < 5)
return;
// Draw circle
graphics.drawOval(xMid - radius, yMid - radius, radius * 2, radius * 2);
// start recursion
//left
drawCircles(graphics, xMid-radius, yMid, radius / 2);
//right
drawCircles(graphics, xMid+radius, yMid, radius / 2);
}
It looks to be like you only have one drawCircles call inside your drawCircles function. This can't be right because each time you draw a circle you need to call the recursive function twice. I see that you are drawing two circles, but that is actually backwards.
To get this to work, you need to draw one circle, and call the recursive function twice.
Here is what you need to change:
Make it so that the drawCircle draws one circle, centered on the coordinates
in drawCircle, call drawCircle twice, once with the left circle coords, once with the right
That should do it.
You are only drawing 1 circle from each side of the big circle. You need to change the code. I only write a short fix but don't tested. Good luck
void drawCircles (Graphics graphics, int xMid, int yMid, int radius)
{
//used to position left and right circles
int x1 = xMid-radius-(radius/2);
int x2 = xMid+radius-(radius/2);
int x3 = xMid+radius+(radius/2);
int x4 = xMid-radius+(radius/2);
int y = yMid-(radius/2);
if (radius > 5)
{
//draw 4 circles
graphics.drawOval(x1, y, (radius/2)*2, (radius/2)*2);
graphics.drawOval(x2, y, (radius/2)*2, (radius/2)*2);
graphics.drawOval(x3, y, (radius/2)*2, (radius/2)*2);
graphics.drawOval(x4, y, (radius/2)*2, (radius/2)*2);
}
//left
drawCircles(graphics, xMid-radius, yMid, radius / 2);
//right
drawCircles(graphics, xMid+radius, yMid, radius / 2);
}
I am trying to draw a rectangle in JPanel that would translate and then rotate itself to mimic the movement of a car. I have been able to make the rectangle translate and rotate, however it rotates around the origin of (0,0). I'm very pleased that I was able to have the rectangle move and rotate as I am very new to Java GUI, but I can not seem to get how to have the rectangle rotate around itself, because I experimented more with it, and when I initialized the rectangle and rotate it 45 degrees it's position was changed, which I would assume is the transform matrix that is appended from the rotate method.
I checked through the site on how would I solve this, however I only found how to rotate a rectangle and not on how to rotate and move like the movement of a simulated car. I would presume it is concerning about its transform matrix, but I'm only speculating. So my question is how would I be able to have the rectangle be able to rotate and move around itself and not against a point in JPanel.
Here's the code that I have come up so far:
public class Draw extends JPanel implements ActionListener {
private int x = 100;
private int y = 100;
private double theta = Math.PI;
Rectangle rec = new Rectangle(x,y,25,25);
Timer timer = new Timer(25,this);
Draw(){
setBackground(Color.black);
timer.start();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setColor(Color.white);
rec.x = 100;
rec.y = 100;
g2d.rotate(theta);
g2d.draw(rec);
g2d.fill(rec);
}
public void actionPerformed(ActionEvent e) {
x = (int) (x + (Math.cos(theta))*1);
y = (int) (y + (Math.sin(theta))*1);
theta = theta - (5*Math.PI/180);
repaint();
}
One of two approaches are commonly used:
Rotate the graphics context around the center (x, y) of the Shape, as shown here.
rotate(double theta, double x, double y)
Translate to the origin, rotate and translate back, as shown here.
g2d.translate(this.getWidth() / 2, this.getHeight() / 2);
g2d.rotate(theta);
g2d.translate(-image.getWidth(null) / 2, -image.getHeight(null) / 2);
Note the apparent reverse order of concatenation in the second example.
Addendum: Looking more closely at your example, the following change rotates the Rectangle around the panel's center.
g2d.rotate(theta, getWidth() / 2, getHeight() / 2);
Also, use the #Override annotation, and give your panel a reasonable preferred size:
#Override
public Dimension getPreferredSize() {
return new Dimension(640, 480);
}
Use affine transform to rotate the rectangle and convert it into the rotated polynomial. Check the code below:
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.white);
/* rotate rectnagle around rec.x and rec.y */
AffineTransform at = AffineTransform.getRotateInstance(theta,
rec.x, rec.y);
/* create the plunomial */
Polygon p = new Polygon();
/* path interator of the affine transformed polynomial */
PathIterator i = rec.getPathIterator(at);
while (!i.isDone()) {
double[] points = new double[2];
i.currentSegment(points);
p.addPoint((int) points[0], (int) points[1]);
i.next();
}
g2d.fill(p);
}