Reputation: 377
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
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...
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...
Upvotes: 2
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
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