rasperryPi
rasperryPi

Reputation: 377

Trying to create a program that draws an ellipse using parametric equation, but the lines aren't showing. Why? (Java)

I am trying to create a program that, using parametric equation, can draw lines between lines and create an ellipse. Here's my code:

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.util.ArrayList;

import javax.swing.JFrame;


public class test extends JFrame{

    ArrayList<Line2D> lines = new ArrayList<>();
    public test(){
        this.setTitle("test");
        this.setSize(800, 600);
        this.setLocationRelativeTo(null);
        this.setLayout(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        drawCircle(3,3.0,3.0);

        this.setVisible(true);


        System.out.println(lines.size());
    }

    public void drawCircle(int radio, double xCenter, double yCenter) {
        double t = 0;
        double xPoint;
        double yPoint;
        double xActual = xCenter;
        double yActual = yCenter + radio*Math.sin(0);
        t += 0.01;

        while(t < 360) {
            xPoint = xCenter + radio*Math.cos(t);
            yPoint = yCenter + radio*Math.sin(t);

           lines.add(new Line2D.Double(xActual, yActual, xPoint, yPoint));
           this.repaint();

            t += 0.01;
            xActual = xPoint;
            yActual = yPoint;
        }
    }

     public void paint(Graphics g) {
         super.paint(g);

         for(Line2D s : lines){
             ((Graphics2D) g).draw(s);
         }
     }
}

I am not getting any errors, but the lines don't seem to appear in the frame. What am I doing wrong?

Upvotes: 1

Views: 991

Answers (3)

MadProgrammer
MadProgrammer

Reputation: 347314

Welcome to the wonderful world of why you shouldn't extend from JFrame and why you shouldn't override paint of top level containers like JFrame

The main problem is, the frame has borders. If you override paint of a JFrame and paint at 0x0, you will actually be painting UNDER the frame. Your circle (at a ratio of 3) is small enough to be painted entirely under the window's title bar.

See How to get the EXACT middle of a screen, even when re-sized, How can I set in the midst? and Java AWT drawString() does not display on window for examples of this problem and why you shouldn't override paint of top level containers

Instead, use a component like JPanel and override it's paintComponent and place your custom painting there. Then place this within an instance of a JFrame, for example...

Panel in frame

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.HeadlessException;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test extends JFrame {

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

    public Test() throws HeadlessException {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Test");
                frame.add(new TestPane());
                frame.pack();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        ArrayList<Line2D> lines = new ArrayList<>();

        public TestPane() {
            drawCircle(3, 3.0, 3.0);
        }

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

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

            g2d.setColor(Color.RED);
            System.out.println(lines.size());
            for (Line2D s : lines) {
                g2d.draw(s);
            }
            g2d.dispose();
        }

        public void drawCircle(int radio, double xCenter, double yCenter) {
            double t = 0;
            double xPoint;
            double yPoint;
            double xActual = xCenter;
            double yActual = yCenter + radio * Math.sin(0);
            t += 0.01;

            while (t < 360) {
                xPoint = xCenter + radio * Math.cos(t);
                yPoint = yCenter + radio * Math.sin(t);

//              System.out.println(xActual + "x" + yActual + "x" + xPoint + "x" + yPoint);
                lines.add(new Line2D.Double(xActual, yActual, xPoint, yPoint));

                t += 0.01;
                xActual = xPoint;
                yActual = yPoint;
            }
        }
    }

}

Your next problem will be, 0x0 (or close enough to it) is the center point of the circle. You need to be able to calculate a x/y offset when you generate the shape so that the top/left corner of the circle is at 0x0 instead

For example, in testing your code, I increased the radio to 100 (to see if it made any difference, which is how I discovered that you were painting under the frame) and it generated something like...

Offset

Upvotes: 2

user4668606
user4668606

Reputation:

Drawing in swing should under all circumstances be done in paintComponent(Graphics), not paint as described in this article. I'd recommend you use a JPanel or any some other nontoplevel component to paint on - which is common habit. And

...
lines.add(new Line2D.Double(xActual, yActual, xPoint, yPoint));
this.repaint();
...

This repaint call will cause some really ugly behaviour and is quite a waste of resources (36000 useless repaints per added shape).

Upvotes: 2

Wyatt Lowery
Wyatt Lowery

Reputation: 513

Create a Graphics2D object. It helps. For example:

Graphics2D g2 = (Graphics2D)g;

Once you have that, you need to set the color. Which you didn't do. Example:

g2.setColor(Color.BLACK);

Also just a tip, override paintComponent(Graphics g) and do NOT override paint().

Upvotes: 0

Related Questions