I'm really stuck on how to go about programming this. How to draw a circle in Java with a radius and points around the edge?
I need to draw a circle within a JFrame with a radius and points around the circumference. i can mathematically calculate how to find the coordinates of the point around the edge but i cant seem to be able to program the circle. I am currently using a Ellipse2D method but that doesn't seem to work and doesn't return a radius, as under my understanding, it doesn't draw the circle from the center rather from a starting coordinate using a height and width.
My current code is on a separate frame but I need to add it to my existing frame.
import java.awt.*;
import javax.swing.*;
import java.awt.geom.*;
public class circle extends JFrame {
public circle() {
super("circle");
setSize(410, 435);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Panel sp = new Panel();
Container content = getContentPane();
content.add(sp);
setContentPane(content);
setVisible(true);
}
public static void main (String args[]){
circle sign = new circle();
}
}
class Panel extends JPanel {
public void paintComponent(Graphics comp) {
super.paintComponent(comp);
Graphics2D comp2D = (Graphics2D) comp;
comp2D.setColor(Color.red);
Ellipse2D.Float sign1 = new Ellipse2D.Float(0F, 0F, 350F, 350F);
comp2D.fill(sign1);
}
}
Points on a circle may be specified as a function of the angle θ:
x = a + r cos(θ)
y = b + r sin(θ)
Here, increments of 2π/8 are shown.
Addendum: As suggested in a comment by #Christoffer Hammarström, this revised example reduces the number of magic numbers in the original. The desired number of points becomes a parameter to the constructor. It also adapts the rendering to the container's size.
/** #see https://stackoverflow.com/questions/2508704 */
public class CircleTest extends JPanel {
private static final int SIZE = 256;
private int a = SIZE / 2;
private int b = a;
private int r = 4 * SIZE / 5;
private int n;
/** #param n the desired number of circles. */
public CircleTest(int n) {
super(true);
this.setPreferredSize(new Dimension(SIZE, SIZE));
this.n = n;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.black);
a = getWidth() / 2;
b = getHeight() / 2;
int m = Math.min(a, b);
r = 4 * m / 5;
int r2 = Math.abs(m - r) / 2;
g2d.drawOval(a - r, b - r, 2 * r, 2 * r);
g2d.setColor(Color.blue);
for (int i = 0; i < n; i++) {
double t = 2 * Math.PI * i / n;
int x = (int) Math.round(a + r * Math.cos(t));
int y = (int) Math.round(b + r * Math.sin(t));
g2d.fillOval(x - r2, y - r2, 2 * r2, 2 * r2);
}
}
private static void create() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new CircleTest(9));
f.pack();
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
create();
}
});
}
}
Try something like this:
public class CirclePanel extends JPanel
{
public static void main(String[] args) throws Exception
{
JFrame f = new JFrame();
f.setContentPane(new CirclePanel());
f.setSize(700,500);
f.setVisible(true);
}
public void paint(Graphics g)
{
super.paint(g);
//Draws the line
g.drawOval(0,0,this.getWidth(), this.getHeight());
//draws filled circle
g.setColor(Color.red);
g.fillOval(0,0,this.getWidth(), this.getHeight());
}
}
You can also override the paint method in the frame class, but then the you would have to calculate in the size of the window decorations and it gets dirty there...
I recommend to take some time to review the "midpoint circle algorithm or Bresenham's circle algorithm". The accepted solution is based on very costly math operations like float multiplication and trigonometric functions.
Related
I would like to draw 50 random dots within a given circle. The problem is the dots are not contained in the circle. Here is a runnable example:
package mygraphicsshapehomework;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
public class MyGraphicsShapeHomeWork extends JFrame {
public static void main(String[] args) {
new MyGraphicsShapeHomeWork();
}
public MyGraphicsShapeHomeWork() {
super("Title");
setBounds(600, 400, 700, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
g2.drawOval(40, 40, 90, 90);
Color newColor = new Color(255, 0, 0);
g2.setColor(newColor);
for (int i = 0; i < 50; i++) {
int x = (int) Math.ceil(Math.random() * 10);
int y = (int) Math.ceil(Math.random() * 10);
g2.fillOval(i+x, i+y, 3, 3); // ???
}
}
}
Here is the result it produces:
How can I draw the dots within the circle only?
To get a random point in a circle with radius R find a random angle and a random radius:
double a = random() * 2 * PI;
double r = R * sqrt(random());
Then the coordinates of the point are:
double x = r * cos(a)
double y = r * sin(a)
Here are some notes about the drawing part. You should not paint directly on top level container such as JFrame. Instead, use JComponent or JPanel. Override paintComponent() for painting rather than paint() and don't forget to call super.paintComponent(g)
Take a look at Performing Custom Painting tutorial for more information.
Do not use setBounds(), override panel's getPreferredSize() and pack() the frame. Also, you rarely need to extend JFrame.
Here is a basic example that demonstrates drawing with a sub-pixel precision:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TestDots extends JPanel{
public static final int POINTS_NUM = 1000;
public static final Color POINT_COLOR = Color.RED;
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
double padding = 10;
double radius = Math.min(this.getWidth(), this.getHeight()) / 2 - padding * 2;
g2.draw(new Ellipse2D.Double(padding, padding, radius * 2, radius * 2));
g2.setColor(POINT_COLOR);
for (int i = 0; i < POINTS_NUM; i++) {
double a = Math.random() * 2 * Math.PI;
double r = radius * Math.sqrt(Math.random());
double x = r * Math.cos(a) + radius + padding;
double y = r * Math.sin(a) + radius + padding;
g2.draw(new Ellipse2D.Double(x, y, 1, 1));
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("TestDots");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.add(new TestDots());
frame.pack();
frame.setVisible(true);
}
});
}
}
Here is a result:
For the position of the dots, generate random coordinates within the bounds of the outer circle. In order to generate these coordinates, the radius of the point from the center of the circle must be less than that of the outer circle. Get a random angle using
float a = Math.random() * Math.PI * 2;
Then, subtract a random value from the outer radius:
outerR - (Math.sqrt(Math.random()) * outerR)
and assign the positions to:
double x = Math.cos(a)*newR;
double y = Math.sin(a)*newR;
I'm sure there is a more mathematical approach to this, but this was the simplest in my opinion.
I wrote a checkerboard program (shown below). My problem is that I can't figure out how to center it with resize, and have it resize proportionately.
I added in a short statement. Int resize (shown below) I did something similiar with a previous program regarding a bullseye where I used a radius. I just haven't the slightest clue how to implement that in here.
import java.awt.*;
import javax.swing.JComponent;
public class CheckerboardComponent extends JComponent {
#Override
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.RED);
int s = 12;
int x = s;
int y = s;
// int resize = Math.min(this.getHeight(), this.getWidth()) / 8 ;
for (int i = 0; i < 8; i++) {
// one row
for (int j = 0; j < 8; j++) {
g2.fill(new Rectangle(x, y, 4 * s, 4 * s) );
x += 4 * s;
if(g2.getColor().equals(Color.RED)){
g2.setColor(Color.BLACK);
}else{
g2.setColor(Color.RED);
}
}
x = s;
y += 4 * s;
if(g2.getColor().equals(Color.RED)){
g2.setColor(Color.BLACK);
}else{
g2.setColor(Color.RED);
}
}
}
}
here is a viewer program
import javax.swing.*;
public class CheckersViewer {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(430, 450);
frame.setTitle("Checkerboard");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
CheckerboardComponent component = new CheckerboardComponent();
frame.add(component);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Hmm... Here's one idea then, though it probably isn't a good one (I'm also not that good with jComponent and jFrame, so there's probably a better way and a more suited person)
I believe the component object has a built-in method called getSize(). If you can relate the size of the rectangle to the size of the window, then it could be resizable. Obviously there would be more code and arguments, but for example:
public void drawStuff(Component c)
{
...
Dimension size = c.getSize();
double RectWidth = (size.width)*(.05);
...
}
check this out for more complete examples:
http://www.javadocexamples.com/java/awt/Component/getSize().html
And I apologize I can't be of more help.
I am trying to display two rotating wheels with diameter 512untis at different rates but i am not able to remove the previous drawn image graphics and set the rotated graphics at the correct position.
For now i am doing a rotation with arbitrary angle.
I tried affineTransform and got the rotations but it was weird like all pixels spread away.
Im using a while loop with thread.sleep(). The following is the code :
//The drawSmallCircle and drawBigCircle return two images.
class MyFramePart2 extends JFrame
{
String name;
JPanel big_obj_panel,small_obj_panel;
JLabel bigLabel,smallLabel;BufferedImage imgRet,imgRetSmall;
static double radians,angle,rev,fps,smallAngle,smallRadians;
int numLines,i=0;
MyFramePart2(String frameName,int numStrokes,double revolutions,double frameps)
{
numLines=numStrokes;
smallAngle=smallRadians=angle=radians=Math.toRadians(360/numLines);
rev=revolutions;
fps=frameps;
setSize(1240,720);
setLocation(0,0);
setLayout(null);
getContentPane().setBackground(Color.WHITE);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
big_obj_panel=new JPanel();
big_obj_panel.setLayout(null);
big_obj_panel.setSize(512,512);
big_obj_panel.setLocation(100,100);
big_obj_panel.setBackground(Color.white);
add(big_obj_panel);
imgRet=drawBigCircle();
bigLabel = new JLabel(new ImageIcon(imgRet));
bigLabel.setLayout(null);
bigLabel.setLocation(0,0);
bigLabel.setSize(512,512);
bigLabel.setOpaque(true);
bigLabel.setBackground(Color.white);
big_obj_panel.add(bigLabel);
small_obj_panel=new JPanel();
small_obj_panel.setLayout(null);
small_obj_panel.setSize(512,512);
small_obj_panel.setLocation(700,100);
small_obj_panel.setBackground(Color.white);
add(small_obj_panel);
imgRetSmall=drawSmallCircle();
smallLabel = new JLabel(new ImageIcon(imgRetSmall));
smallLabel.setLayout(null);
smallLabel.setLocation(0,0);
smallLabel.setSize(512,512);
smallLabel.setOpaque(true);
smallLabel.setBackground(Color.white);
small_obj_panel.add(smallLabel);
setVisible(true);
while(i!=5) // suppose to be while true, just checking
{
setVisible(true);
bigLabel.setIcon(new ImageIcon(imgRet));
smallLabel.setIcon(new ImageIcon(imgRetSmall));
try{
Thread.sleep(10);
}
catch(Exception e)
{}
i++;
}
}
#Override
public void paint(Graphics g)
{
super.paint(g);
Graphics2D g2d=(Graphics2D)g;
g2d.translate(256,256);
g2d.rotate(Math.toRadians(20));
g2d.translate(-256,-256);
g2d.drawImage(imgRet,0,0,null);
g2d.dispose();
super.paint(g);
g2d=(Graphics2D)g;
g2d.translate(256,256);
g2d.rotate(Math.toRadians(30));
g2d.translate(-256,-256);
g2d.drawImage(imgRetSmall,0,0,null);
g2d.dispose();
}
public static BufferedImage drawBigCircle()
{
BufferedImage img=new BufferedImage(512,512,BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d=img.createGraphics();
g2d.setColor(Color.black);
g2d.drawOval(0,0,511,511);
Line2D l2d;
while(angle <= 2*Math.PI)
{
l2d=new Line2D.Double(256,256,256+256*Math.cos(angle),256+256*Math.sin(angle));
g2d.draw(l2d);
angle=angle+radians;
}
return img;
}
}
First rule of Swing. Don't block the Event Dispatching Thread. Doing so will make you application look like it's hung and prevent the EDT from processing any repaint requests.
This means, you need some way to schedule updates that doesn't block the EDT
Second rule of Swing. Don't create or modify any UI component from any thread other then the EDT.
Generally, you should avoid overriding the paint method of top level containers like JFrame, apart from everything else, they're not double buffered, meaning your painting will flicker as it's updated. Instead, you should use one of the Swing containers, like JPanel
There are lots of different ways to achieve this. Basically, here I've used three lists, but if I was serious, I would create an object that could maintain all the required information (image, angle an delta)
In order to achieve the actual animation, I've used a javax.swing.Timer. This will trigger an event at least every n periods, but more importantly, it does it within the context of the Event Dispatching Thread. This ensures that all the changes made to the angles are done in way that will prevent any possibility of painting occurring while we're updating the values...
This example rotates the three images at different (random) speeds...
public class TestRotation {
public static void main(String[] args) {
new TestRotation();
}
public TestRotation() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new AnimationPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class AnimationPane extends JPanel {
private List<BufferedImage> images;
private List<Double> angles;
private List<Double> speed;
public AnimationPane() {
images = new ArrayList<>(5);
images.add(createWheel(50, 4));
images.add(createWheel(50, 3));
images.add(createWheel(50, 6));
angles = new ArrayList<>();
speed = new ArrayList<>();
for (int index = 0; index < images.size(); index++) {
angles.add(0d);
speed.add(Math.random() * 5d);
}
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (int index = 0; index < angles.size(); index++) {
double angle = angles.get(index);
double delta = speed.get(index);
angle += delta;
angles.set(index, angle);
}
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int x = 0;
int y = 0;
for (int index = 0; index < images.size(); index++) {
BufferedImage image = images.get(index);
double angle = angles.get(index);
// This is important. Basically we going to grab a isolated snap shot
// of the current graphics context. This means any changes we make
// will not affect the original graphics context (other then painting)
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
AffineTransform at = new AffineTransform();
at.translate(x, y);
at.rotate(Math.toRadians(angle), image.getWidth() / 2, image.getHeight() / 2);
g2d.setTransform(at);
g2d.drawImage(image, 0, 0, this);
g2d.dispose();
x += image.getWidth();
}
}
}
protected Point2D calculateOutterPoint(int radius, double angel) {
int x = Math.round(radius / 2);
int y = Math.round(radius / 2);
double rads = Math.toRadians((angel + 90));
// This determins the length of tick as calculate from the center of
// the circle. The original code from which this derived allowed
// for a varible length line from the center of the cirlce, we
// actually want the opposite, so we calculate the outter limit first
double fullLength = (radius / 2d);
// Calculate the outter point of the line
double xPosy = (x + Math.cos(rads) * fullLength);
double yPosy = (y - Math.sin(rads) * fullLength);
return new Point2D.Double(xPosy, yPosy);
}
public BufferedImage createWheel(int radius, int spokes) {
BufferedImage img = new BufferedImage(radius, radius, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.black);
g2d.drawOval(0, 0, radius - 1, radius - 1);
Point2D center = new Point2D.Double(radius / 2d, radius / 2d);
double angle = 360d / spokes;
for (int index = 0; index < spokes; index++) {
Point2D p = calculateOutterPoint(radius, index * angle);
g2d.draw(new Line2D.Double(center, p));
}
g2d.dispose();
return img;
}
}
I know the following code will move an object in a straight line. How can I get the object to travel in a wavy line? I know that something extra is required for the x variable.
public void draw(Graphics2D g)
{
g.setColor(Color.WHITE);
g.fillOval ((int) (x - r), (int) (y - r), (int)
(2 * r),
(int) (2 * r));
y++;
if (y - r > height)
y = -r;
}
Use the sine or cosine function to calculate y as a function of x.
Multiply the sine or cosine function to increase the amplitude (how high it goes)
y = 100 * sin(x) // will make it have peaks of -100 and 100
Divide the x to increase the period. (distance between peaks)
y = sin(x/2) // will make it take twice the x distance between peaks.
Something like this:
public void draw(Graphics2D g)
{
g.setColor(Color.WHITE);
g.fillOval ((int) (x - r), (int) (y - r), (int)
(2 * r),
(int) (2 * r));
x++; // Left to right movement
// Example, modify the multipliers as necessary
y = 100 * Math.sin(Math.toDegrees(x/4))
}
Including a sin(x) or cos(x) in your function will provide a regular wave pattern, irregular pattern needs a more sophisticated function
I know you already accepted an answer, but here's something to draw additional inspiration from that I whipped up...
package wavy;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Wavy {
public static void main(String[] args) {
final JFrame frame = new JFrame("Wavy!");
final WavyPanel wp = new WavyPanel();
frame.getContentPane().add(wp, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final Ticker t = new Ticker(wp);
final Repainter r = new Repainter(wp);
frame.pack();
frame.setVisible(true);
final Timer tickTimer = new Timer();
final Timer paintTimer = new Timer();
paintTimer.schedule(r, 1000, 50);
tickTimer.schedule(t, 1000, 10);
}
private static class WavyPanel extends JPanel {
private final Dimension size = new Dimension(640, 480);
private int amplitude = 50;
private int frequency = 5;
private int x = 0;
private double y = size.height / 2;
private int yBase = 0;
WavyPanel() {
super(true);
}
#Override
protected void paintComponent(final Graphics g) {
final Graphics2D g2 = (Graphics2D)g;
g2.setColor(Color.WHITE);
g2.fillRect(0, 0, size.width, size.height);
g2.setColor(Color.BLACK);
g2.fillOval(x, (int)y, 30, 30);
}
#Override
public Dimension getPreferredSize() {
return size;
}
#Override
public Dimension getMinimumSize() {
return size;
}
#Override
public Dimension getMaximumSize() {
return size;
}
public void tick() {
//Move a pixel to the right; loop over to the left when reaching edge
x = (++x) % size.width;
//Length of one full wave = panel width divided by frequency
final int waveLength = size.width / frequency;
//Incrementing yBase; capping off at wavelength
yBase = (++yBase) % waveLength;
//Normalizing to [0..1]
final double normalized = (double)yBase / (double)waveLength;
//Full wave at 2*pi, means...
final double radians = normalized * Math.PI * 2;
//Getting the sine
final double sine = Math.sin(radians);
//Multiplying with amplitude, add to center position and we have our y
y = (int)(sine * amplitude) + size.height/2;
}
}
private static class Ticker extends TimerTask {
private final WavyPanel panel;
Ticker(final WavyPanel panel) {
this.panel = panel;
}
#Override
public void run() {
panel.tick();
}
}
private static class Repainter extends TimerTask {
private final WavyPanel panel;
Repainter(final WavyPanel panel) {
this.panel = panel;
}
#Override
public void run() {
panel.repaint();
}
}
}
This should run at an approximate 20 frames per second. You can increase this by setting the second argument of paintTimer.schedule(r, 1000, 50) lower. The speed of movement can be altered by lowering (speeding up) or increasing (slower) the second argument of tickTimer.schedule(t, 1000, 50).
Changing the amplitude field of WavyPanel will change how high/low the circle moves. Changing the frequency to a higher value will result in shorter waves, while a lower value will produce longer waves.
With some additional work you could add in controls to change the amplitude and frequency on-the-fly. Some additional notes:
You may wish to add some safeguard to the tick() method to make sure that when one invocation is already running, additional ones are skipped until the first one is done. Otherwise the calculations could fail for short tick intervals. A semaphore could be used here.
Since trigonometric calculations aren't exactly the cheapest, you may consider caching some results (e.g. in an array) for re-use if many similar animations are to be played or if there's a lot more drawing going on.
I hope I'm interpreting this right. Could use the sine or cosine of either your x or y coordinate. I'm not at a machine with java so I can't make an example at the moment..
You're right that you need to update both the x and y variables to get a wavy line. Here's the general strategy for a horizontal line that is wavy up and down:
Choose a function f(x) that has the shape you want. This will be used to calculate values for y. (For instance, you can use y = amplitude * Math.sin(frequency * x) to get a regular sine wave of a given amplitude and frequency.)
If necessary, write the code that implements your function.
Set x to some initial value.
In draw, before you paint the oval, calculate y = f(x);. Paint the oval and then increment x. If necessary, reset x so it stays in range.
If you want a vertical line that is wavy left and right, just reverse the roles of x and y in the above. If you want the oval to go in the reverse direction, just decrement instead of increment in step 4.
this sample is for point(Line with one length) on sinus graph and clock using.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class RunSwing extends JPanel {
static int x1 = 500;
static int y1 = 500;
static int x2 = x1;
static int y2 = y1;
final static int vectorLength = 100;
final static int sinx2 = x2;
final static int siny2 = y2;
static double count = 0;
private static RunSwing run = new RunSwing();
final Timer print = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(final ActionEvent e) {
//increaseSinusGraph();
increaseClockVector();
count+=6; //for clock for 1 second
/*count++;//for sinus*/
if (count % 360 == 0)
System.out.println((count / 360) + " minute passed");
}
});
RunSwing() {
print.start();
}
public static void main(String[] args) {
JFrame frame = new JFrame("amir");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(run);
frame.setSize(1100, 700);
frame.setVisible(true);
}
static void increaseClockVector() {
double cos = Math.cos(Math.toRadians(count));
double sin = Math.sin(Math.toRadians(count));
y2 = siny2 + (int) (vectorLength * sin);
x2 = sinx2 + (int) (vectorLength * cos);
}
static void increaseSinusGraph() {
double sin = Math.sin(Math.toRadians(count));
y2 = siny2 + (int) (vectorLength * sin);
x2++;
}
private void createPoint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.drawLine(x2, y2, x2 + 1, y2 + 1);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(0, 0, 0));
g.drawLine(x1, y1, x2, y2);//for clock
/*g.drawLine(x2, y2, x2+1, y2+1);//for sinus*/
repaint();
}
}
im trying to make a swing app that draws a function's graph(simple for now ex. x+2)
but i'm having problems to make mathematical coordinates of my points depending on screen coordinates .
I want it to simply draw a line that goes from P1(0,1) to P2(1,2) inside my graph.
here is my code :
import java.awt.*;
import javax.swing.*;
public class Graph extends JPanel {
protected void paintComponent(Graphics g) {
int YP1,YP2;
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
int h = getHeight();
int w = getWidth();
// Draw axeX.
g2.draw(new Line2D.Double(0, h/2, w, h/2)); //to make axisX in the middle
// Draw axeY.
g2.draw(new Line2D.Double(w/2,h,w/2,0));//to make axisY in the middle of the panel
//line between P1(0,1) and P2(1,2) to draw function x+1
Point2D P1 = new Point2D.Double(w/2,(h/2)+1);
Point2D P2 = new Point2D.Double((w/2)+1,(h/2)+2);
g2.draw(new Line2D.Double(P1,P2));
}
public static void main(String[] args) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new Graphe());
f.setSize(400,400);
f.setLocation(200,200);
f.setVisible(true);
}
}
thanks.
import java.awt.*;
import javax.swing.*;
public class Graph extends JPanel {
private static final int UNIT = 20;
protected void paintComponent(Graphics g) {
int YP1,YP2;
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
int h = getHeight();
int w = getWidth();
// Draw axeX.
g2.draw(new Line2D.Double(0, h/2, w, h/2)); //to make axisX in the middle
// Draw axeY.
g2.draw(new Line2D.Double(w/2,h,w/2,0));//to make axisY in the middle of the panel
//line between P1(0,1) and P2(1,2) to draw function x+1
Point2D P1 = new Point2D.Double(w/2,(h/2)+ UNIT);
Point2D P2 = new Point2D.Double((w/2)+ UNIT,(h/2)+ 2*UNIT); //considering 20 = 1 unit in your syste,
g2.draw(new Line2D.Double(P1,P2));
}
public static void main(String[] args) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new Graphe());
f.setSize(400,400);
f.setLocation(200,200);
f.setVisible(true);
}
}
Tryout this code read comments to get the solution
The center of your coordinate system (0,0) is painted at (w/2, h/2). The missing part is the scale, in other words: how many pixels make one unit on the x axis and y axis.
So usually you multiply your unit value by the scaling factor (like 10, if you want 10 pixel per unit) and add the offset of the axis from the left or lower boundary. The annoying part is the (0,0) on screen coordinates is the upper left corner and height counts from top to bottom (reversed y axis). That makes it a bit more complicated:
xOnScreenPos = (xUnit * xScale) + xScaleOffset;
yOnScreenPos = -(yUnit * yScale) + yScaleOffset;