Store random line values in data structure - java

I am trying to create a program which creates 9 biomorphs which are evolved somehow from a middle biomorph. Currently, I have 9 showing although these are completely random. What is the best way to store the values of the initial biomorph to be used in the other 8?
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;
import javax.swing.JPanel;
public class BiomorphObject extends JPanel {
Graphics2D g2d;
Dimension size = getSize();
int w = size.width;
int h = size.height;
Random ran = new Random();
int x1;
int x2;
int y1;
int y2;
public BiomorphObject(Graphics g){
g2d = (Graphics2D) g;
g2d.setColor(Color.BLUE);
Random ran = new Random();
int x = Math.abs(ran.nextInt(100)) % w + 120;
int y = Math.abs(ran.nextInt(100)) % h;
int xMirror = x - 120;
g2d.drawLine(120, 85, x, y);
g2d.drawLine(120, 85, 120 - xMirror, y);
x1 = x;
y1 = y;
x2 = Math.abs(ran.nextInt(50)) % w + 120;
y2 = Math.abs(ran.nextInt(50)) % h;
paintBiomorph(g);
}
public void paintBiomorph(Graphics g) {
super.paintComponent(g);
for (int i = 0; i <= 10; i++) {
int xMirror1 = x1 - 120;
int xMirror2 = x2 - 120;
g2d.drawLine(x1, y1, x2, y2);
g2d.drawLine(120 - xMirror1, y1, 120 - xMirror2, y2);
x1 = x2;
y1 = y2;
x2 = Math.abs(ran.nextInt(100)) % w + 120;
y2 = Math.abs(ran.nextInt(100)) % h;
}
}
}
This is a screenshot of the current GUI I have:

You should not use the Random() method in a painting method. You can't control when Swing will repaint a component and you don't want the painting to randomly change.
Instead you need to create properties in your class that the painting method can use to do the custom painting. So you should create a Biomorph object. This object will contain the information necessary to paint a single Biomorph. It should even contain a method to paint itself. Lets call this method paintBiomorph(Graphics).
When you create the Biomorph object you might have an empty constructor which creates a random Biomorph, then you might have a constructor that takes a Biomporh object as a parameter so you can create "child" Biomorphs based on a "parent" Biomorph.
Then you can create an ArrayList hold multiple Biomorh objects. Then in the paintComponent() method you iterate through the ArrayList and simply invoke the paintBoimorph(GRaphics) method on each Biomorph object.
The Random() method would only be used when you initially create a Biomorph object. After than all the data need to repaint the Biomorph must be part of the object itself.
Edit:
The Biomorph class might look something like:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;
import javax.swing.JPanel;
public class Biomorph extends JPanel
{
List<Shape> lines = new ArrayList<Shape>();
//Graphics2D g2d;
//Dimension size = getSize();
//int w = size.width;
//int h = size.height;
//Random ran = new Random();
//int x1;
//int x2;
//int y1;
//int y2;
public Biomorph()
{
//g2d = (Graphics2D) g;
//g2d.setColor(Color.BLUE);
setForeground(Color.BLUE);
Random ran = new Random();
int x = Math.abs(ran.nextInt(100)) + 120;
int y = Math.abs(ran.nextInt(100));
int xMirror = x - 120;
// g2d.drawLine(120, 85, x, y);
// g2d.drawLine(120, 85, 120 - xMirror, y);
lines.add( new Line2D.Double(120, 85, x, y);
lines.add( new Line2D.Double(120, 85, -x, y);
int x1 = x;
int y1 = y;
int x2 = Math.abs(ran.nextInt(50)) + 120;
int y2 = Math.abs(ran.nextInt(50));
for (int i = 0; i <= 10; i++) {
int xMirror1 = x1 - 120;
int xMirror2 = x2 - 120;
//g2d.drawLine(x1, y1, x2, y2);
//g2d.drawLine(120 - xMirror1, y1, 120 - xMirror2, y2);
lines.add( new Line2D.Double(x1, y1, x2, y2);
lines.add( new Line2D.Double(-x1, y1, -x2, y2);
x1 = x2;
y1 = y2;
x2 = Math.abs(ran.nextInt(100)) + 120;
y2 = Math.abs(ran.nextInt(100));
}
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g.create();
g2d.setColor( getForeground() );
for (Shape line: lines)
{
g2d.fill( line );
//g2d.draw( line );
}
g2d.dispose();
}
}

Related

Draw Line Graph2D with data [duplicate]

In my program I want to draw a simple score line graph. I have a text file and on each line is an integer score, which I read in and want to pass as argument to my graph class. I'm having some trouble implementing the graph class and all the examples I've seen have their methods in the same class as their main, which I won't have.
I want to be able to pass my array to the object and generate a graph, but when calling my paint method it is asking me for a Graphics g... This is what I have so far:
public class Graph extends JPanel {
public void paintGraph (Graphics g){
ArrayList<Integer> scores = new ArrayList<Integer>(10);
Random r = new Random();
for (int i : scores){
i = r.nextInt(20);
System.out.println(r);
}
int y1;
int y2;
for (int i = 0; i < scores.size(); i++){
y1 = scores.get(i);
y2 = scores.get(i+1);
g.drawLine(i, y1, i+1, y2);
}
}
}
For now I have inserted a simple random number generator to fill up my array.
I have an existing frame and basically want to instantiate the Graph class and mount the panel onto my frame. I'm really sorry that this question seems so jumbled by the way, but I've had little sleep...
The code in my main statement is:
testFrame = new JFrame();
testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Graph graph = new Graph();
testFrame.add(graph);
I'm not sure exactly what an SSCE is but this is my attempt at one:
public class Test {
JFrame testFrame;
public Test() {
testFrame = new JFrame();
testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Graph graph = new Graph();
testFrame.add(graph);
testFrame.setBounds(100, 100, 764, 470);
testFrame.setVisible(true);
}
Graph.java
public class Graph extends JPanel {
public Graph() {
setSize(500, 500);
}
#Override
public void paintComponent(Graphics g) {
Graphics2D gr = (Graphics2D) g; // This is if you want to use Graphics2D
// Now do the drawing here
ArrayList<Integer> scores = new ArrayList<Integer>(10);
Random r = new Random();
for (int i : scores) {
i = r.nextInt(20);
System.out.println(r);
}
int y1;
int y2;
for (int i = 0; i < scores.size() - 1; i++) {
y1 = (scores.get(i)) * 10;
y2 = (scores.get(i + 1)) * 10;
gr.drawLine(i * 10, y1, (i + 1) * 10, y2);
}
}
}
Problems with your code and suggestions:
Again you need to change the preferredSize of the component (here the Graph JPanel), not the size
Don't set the JFrame's bounds.
Call pack() on your JFrame after adding components to it and before calling setVisible(true)
Your foreach loop won't work since the size of your ArrayList is 0 (test it to see that this is correct). Instead use a for loop going from 0 to 10.
You should not have program logic inside of your paintComponent(...) method but only painting code. So I would make the ArrayList a class variable and fill it inside of the class's constructor.
For example:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.*;
#SuppressWarnings("serial")
public class DrawGraph extends JPanel {
private static final int MAX_SCORE = 20;
private static final int PREF_W = 800;
private static final int PREF_H = 650;
private static final int BORDER_GAP = 30;
private static final Color GRAPH_COLOR = Color.green;
private static final Color GRAPH_POINT_COLOR = new Color(150, 50, 50, 180);
private static final Stroke GRAPH_STROKE = new BasicStroke(3f);
private static final int GRAPH_POINT_WIDTH = 12;
private static final int Y_HATCH_CNT = 10;
private List<Integer> scores;
public DrawGraph(List<Integer> scores) {
this.scores = scores;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
double xScale = ((double) getWidth() - 2 * BORDER_GAP) / (scores.size() - 1);
double yScale = ((double) getHeight() - 2 * BORDER_GAP) / (MAX_SCORE - 1);
List<Point> graphPoints = new ArrayList<Point>();
for (int i = 0; i < scores.size(); i++) {
int x1 = (int) (i * xScale + BORDER_GAP);
int y1 = (int) ((MAX_SCORE - scores.get(i)) * yScale + BORDER_GAP);
graphPoints.add(new Point(x1, y1));
}
// create x and y axes
g2.drawLine(BORDER_GAP, getHeight() - BORDER_GAP, BORDER_GAP, BORDER_GAP);
g2.drawLine(BORDER_GAP, getHeight() - BORDER_GAP, getWidth() - BORDER_GAP, getHeight() - BORDER_GAP);
// create hatch marks for y axis.
for (int i = 0; i < Y_HATCH_CNT; i++) {
int x0 = BORDER_GAP;
int x1 = GRAPH_POINT_WIDTH + BORDER_GAP;
int y0 = getHeight() - (((i + 1) * (getHeight() - BORDER_GAP * 2)) / Y_HATCH_CNT + BORDER_GAP);
int y1 = y0;
g2.drawLine(x0, y0, x1, y1);
}
// and for x axis
for (int i = 0; i < scores.size() - 1; i++) {
int x0 = (i + 1) * (getWidth() - BORDER_GAP * 2) / (scores.size() - 1) + BORDER_GAP;
int x1 = x0;
int y0 = getHeight() - BORDER_GAP;
int y1 = y0 - GRAPH_POINT_WIDTH;
g2.drawLine(x0, y0, x1, y1);
}
Stroke oldStroke = g2.getStroke();
g2.setColor(GRAPH_COLOR);
g2.setStroke(GRAPH_STROKE);
for (int i = 0; i < graphPoints.size() - 1; i++) {
int x1 = graphPoints.get(i).x;
int y1 = graphPoints.get(i).y;
int x2 = graphPoints.get(i + 1).x;
int y2 = graphPoints.get(i + 1).y;
g2.drawLine(x1, y1, x2, y2);
}
g2.setStroke(oldStroke);
g2.setColor(GRAPH_POINT_COLOR);
for (int i = 0; i < graphPoints.size(); i++) {
int x = graphPoints.get(i).x - GRAPH_POINT_WIDTH / 2;
int y = graphPoints.get(i).y - GRAPH_POINT_WIDTH / 2;;
int ovalW = GRAPH_POINT_WIDTH;
int ovalH = GRAPH_POINT_WIDTH;
g2.fillOval(x, y, ovalW, ovalH);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
List<Integer> scores = new ArrayList<Integer>();
Random random = new Random();
int maxDataPoints = 16;
int maxScore = 20;
for (int i = 0; i < maxDataPoints ; i++) {
scores.add(random.nextInt(maxScore));
}
DrawGraph mainPanel = new DrawGraph(scores);
JFrame frame = new JFrame("DrawGraph");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Which will create a graph that looks like so:
Just complementing Hovercraft Full Of Eels's solution:
I reworked his code, tweaked it a bit, adding a grid, axis labels and now the Y-axis goes from the minimum value present up to the maximum value. I planned on adding a couple of getters/setters but I didn't need them, you can add them if you want.
Here is the Gist link, I'll also paste the code below: GraphPanel on Gist
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class GraphPanel extends JPanel {
private int width = 800;
private int heigth = 400;
private int padding = 25;
private int labelPadding = 25;
private Color lineColor = new Color(44, 102, 230, 180);
private Color pointColor = new Color(100, 100, 100, 180);
private Color gridColor = new Color(200, 200, 200, 200);
private static final Stroke GRAPH_STROKE = new BasicStroke(2f);
private int pointWidth = 4;
private int numberYDivisions = 10;
private List<Double> scores;
public GraphPanel(List<Double> scores) {
this.scores = scores;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
double xScale = ((double) getWidth() - (2 * padding) - labelPadding) / (scores.size() - 1);
double yScale = ((double) getHeight() - 2 * padding - labelPadding) / (getMaxScore() - getMinScore());
List<Point> graphPoints = new ArrayList<>();
for (int i = 0; i < scores.size(); i++) {
int x1 = (int) (i * xScale + padding + labelPadding);
int y1 = (int) ((getMaxScore() - scores.get(i)) * yScale + padding);
graphPoints.add(new Point(x1, y1));
}
// draw white background
g2.setColor(Color.WHITE);
g2.fillRect(padding + labelPadding, padding, getWidth() - (2 * padding) - labelPadding, getHeight() - 2 * padding - labelPadding);
g2.setColor(Color.BLACK);
// create hatch marks and grid lines for y axis.
for (int i = 0; i < numberYDivisions + 1; i++) {
int x0 = padding + labelPadding;
int x1 = pointWidth + padding + labelPadding;
int y0 = getHeight() - ((i * (getHeight() - padding * 2 - labelPadding)) / numberYDivisions + padding + labelPadding);
int y1 = y0;
if (scores.size() > 0) {
g2.setColor(gridColor);
g2.drawLine(padding + labelPadding + 1 + pointWidth, y0, getWidth() - padding, y1);
g2.setColor(Color.BLACK);
String yLabel = ((int) ((getMinScore() + (getMaxScore() - getMinScore()) * ((i * 1.0) / numberYDivisions)) * 100)) / 100.0 + "";
FontMetrics metrics = g2.getFontMetrics();
int labelWidth = metrics.stringWidth(yLabel);
g2.drawString(yLabel, x0 - labelWidth - 5, y0 + (metrics.getHeight() / 2) - 3);
}
g2.drawLine(x0, y0, x1, y1);
}
// and for x axis
for (int i = 0; i < scores.size(); i++) {
if (scores.size() > 1) {
int x0 = i * (getWidth() - padding * 2 - labelPadding) / (scores.size() - 1) + padding + labelPadding;
int x1 = x0;
int y0 = getHeight() - padding - labelPadding;
int y1 = y0 - pointWidth;
if ((i % ((int) ((scores.size() / 20.0)) + 1)) == 0) {
g2.setColor(gridColor);
g2.drawLine(x0, getHeight() - padding - labelPadding - 1 - pointWidth, x1, padding);
g2.setColor(Color.BLACK);
String xLabel = i + "";
FontMetrics metrics = g2.getFontMetrics();
int labelWidth = metrics.stringWidth(xLabel);
g2.drawString(xLabel, x0 - labelWidth / 2, y0 + metrics.getHeight() + 3);
}
g2.drawLine(x0, y0, x1, y1);
}
}
// create x and y axes
g2.drawLine(padding + labelPadding, getHeight() - padding - labelPadding, padding + labelPadding, padding);
g2.drawLine(padding + labelPadding, getHeight() - padding - labelPadding, getWidth() - padding, getHeight() - padding - labelPadding);
Stroke oldStroke = g2.getStroke();
g2.setColor(lineColor);
g2.setStroke(GRAPH_STROKE);
for (int i = 0; i < graphPoints.size() - 1; i++) {
int x1 = graphPoints.get(i).x;
int y1 = graphPoints.get(i).y;
int x2 = graphPoints.get(i + 1).x;
int y2 = graphPoints.get(i + 1).y;
g2.drawLine(x1, y1, x2, y2);
}
g2.setStroke(oldStroke);
g2.setColor(pointColor);
for (int i = 0; i < graphPoints.size(); i++) {
int x = graphPoints.get(i).x - pointWidth / 2;
int y = graphPoints.get(i).y - pointWidth / 2;
int ovalW = pointWidth;
int ovalH = pointWidth;
g2.fillOval(x, y, ovalW, ovalH);
}
}
// #Override
// public Dimension getPreferredSize() {
// return new Dimension(width, heigth);
// }
private double getMinScore() {
double minScore = Double.MAX_VALUE;
for (Double score : scores) {
minScore = Math.min(minScore, score);
}
return minScore;
}
private double getMaxScore() {
double maxScore = Double.MIN_VALUE;
for (Double score : scores) {
maxScore = Math.max(maxScore, score);
}
return maxScore;
}
public void setScores(List<Double> scores) {
this.scores = scores;
invalidate();
this.repaint();
}
public List<Double> getScores() {
return scores;
}
private static void createAndShowGui() {
List<Double> scores = new ArrayList<>();
Random random = new Random();
int maxDataPoints = 40;
int maxScore = 10;
for (int i = 0; i < maxDataPoints; i++) {
scores.add((double) random.nextDouble() * maxScore);
// scores.add((double) i);
}
GraphPanel mainPanel = new GraphPanel(scores);
mainPanel.setPreferredSize(new Dimension(800, 600));
JFrame frame = new JFrame("DrawGraph");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
It looks like this:
Or simply use the JFreechart library - http://www.jfree.org/jfreechart/ .
There exist many open source projects that handle all the drawing of line charts for you with a couple of lines of code. Here's how you can draw a line chart from data in a couple text (CSV) file with the XChart library. Disclaimer: I'm the lead developer of the project.
In this example, two text files exist in ./CSV/CSVChartRows/. Notice that each row in the files represents a data point to be plotted and that each file represents a different series. series1 contains x, y, and error bar data, whereas series2 contains just x and y, data.
series1.csv
1,12,1.4
2,34,1.12
3,56,1.21
4,47,1.5
series2.csv
1,56
2,34
3,12
4,26
Source Code
public class CSVChartRows {
public static void main(String[] args) throws Exception {
// import chart from a folder containing CSV files
XYChart chart = CSVImporter.getChartFromCSVDir("./CSV/CSVChartRows/", DataOrientation.Rows, 600, 400);
// Show it
new SwingWrapper(chart).displayChart();
}
}
Resulting Plot
Override the paintComponent method of your panel so you can custom draw. Like this:
#Override
public void paintComponent(Graphics g) {
Graphics2D gr = (Graphics2D) g; //this is if you want to use Graphics2D
//now do the drawing here
...
}
Hovercraft Full Of Eels' answer is very good, but i had to change it a bit in order to get it working on my program:
int y1 = (int) ((this.height - 2 * BORDER_GAP) - (values.get(i) * yScale - BORDER_GAP));
instead of
int y1 = (int) (scores.get(i) * yScale + BORDER_GAP);
because if i used his way the graphic would be upside down
(you'd see it if you used hardcoded values (e.g 1,3,5,7,9) instead of random values)

How to draw a line of x, y points in java where x and y are double type?

How can I draw a line of x, y points? I tried using Graphics 2D but I get the error "The method drawLine(int, int, int, int) in the type Graphics is not applicable for the arguments (double, double, double, double)". How can I plot the line in java if I don't use Graphics 2D?
public void paint(Graphics g){
float []data= Series.getY();
double x1 = 0;
double y1 = 0;
for (int i = 0; i < data.length; i++){
double x2 = i;
double y2 = data[i];
g.drawLine(x1, y1, x2, y2);
y1 = y2;
x1 = x2;
}
}
I have tried this
public class PlotPanel {
public void paint (Graphics g) {
float []data= Series.getY();
Graphics2D g2 = (Graphics2D) g;
double y1 = 0;
double x1 = 0;
for (int i = 0; i < data.length; i++){
double x2 = i;
double y2 = data[i];
g2.draw(new Line2D.Double(x1, y1, x2, y2));
y1 = y2;
x1 = x2;
}
}
public static void main(String args[]) {
PlotPanel pp = new PlotPanel();
pp.paint(g2);
}
}
It says g2 cannot be resolved to a variable. How can I check if it works?
The prototype of drawLine is drawLine(int, int, int, int) and you give to drawLine 4 variable of type double. You can test to swap all of double in int.
Hope help you.

Can't: draw Ovals and Rectangles together, only individually

What I'm trying to do here is generate 5 random ovals and rectangles. If I remove
for(MyOval oval : ovals){
oval.draw(g);
}
from the first class, it will display 5 random rectangles. If I remove
for(MyRectangle rectangle : rectangles){
rectangle.draw(g);
}
it will display 5 random ovals. If I remove nothing, it doesn't work. What I'm doing wrong?
DrawPanel Class
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JPanel;
public class DrawPanel extends JPanel{
private Random randomNumbers = new Random();
private MyOval[] ovals;
private MyRectangle[] rectangles;
public DrawPanel(){
setBackground(Color.WHITE);
ovals = new MyOval[ 5 + randomNumbers.nextInt(5)];
rectangles = new MyRectangle [ 5 + randomNumbers.nextInt(5)];
for (int count = 0; count <ovals.length; count++){
int x1 = randomNumbers.nextInt(300);
int y1 = randomNumbers.nextInt(300);
int x2 = randomNumbers.nextInt(300);
int y2 = randomNumbers.nextInt(300);
Color color = new Color (randomNumbers.nextInt(256), randomNumbers.nextInt(256), randomNumbers.nextInt(256));
ovals[count] = new MyOval(x1, y1, x2, y2, color);
rectangles[count] = new MyRectangle(x1, y1, x2, y2, color);
}
}
public void paintComponent(Graphics g){
super.paintComponent(g);
for(MyRectangle rectangle : rectangles){
rectangle.draw(g);
}
for(MyOval oval : ovals){
oval.draw(g);
}
}
}
Main Class
import javax.swing.JFrame;
public class TestDraw {
public static void main(String[] args) {
DrawPanel panel = new DrawPanel();
JFrame application = new JFrame();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.add(panel);
application.setSize(300,300);
application.setVisible(true);
}
}
MyOval Class
import java.awt.Color;
import java.awt.Graphics;
public class MyOval {
private int x1;
private int y1;
private int x2;
private int y2;
private Color myColor;
public MyOval(int x1, int y1, int x2, int y2, Color color){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
myColor = color;
}
public void draw(Graphics g){
g.setColor(myColor);
g.drawOval(x1, y1, x2, y2);
}
}
MyRectangle Class
import java.awt.Color;
import java.awt.Graphics;
public class MyRectangle {
private int x1;
private int y1;
private int x2;
private int y2;
private Color myColor;
public MyRectangle(int x1, int y1, int x2, int y2, Color color){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
myColor = color;
}
public void draw(Graphics g){
g.setColor(myColor);
g.drawRect(x1, y1, x2, y2);
}
}
The problem is that you are allocating two arrays with random length, but then using the length of the first array to iterate through both arrays.
Quote:
ovals = new MyOval[ 5 + randomNumbers.nextInt(5)];
rectangles = new MyRectangle [ 5 + randomNumbers.nextInt(5)];
for (int count = 0; count <ovals.length; count++){
int x1 = randomNumbers.nextInt(300);
int y1 = randomNumbers.nextInt(300);
int x2 = randomNumbers.nextInt(300);
int y2 = randomNumbers.nextInt(300);
Color color = new Color (randomNumbers.nextInt(256), randomNumbers.nextInt(256), randomNumbers.nextInt(256));
ovals[count] = new MyOval(x1, y1, x2, y2, color);
rectangles[count] = new MyRectangle(x1, y1, x2, y2, color);
}
Solution is to either initialize the elements in each array separately up to their length, or if you intended both arrays to be the same length you could choose one random length before you allocate the arrays. Latter fix would be as shown below:
int len = 5 + randomNumbers.nextInt(5);
ovals = new MyOval[ len ];
rectangles = new MyRectangle [ len ];
By doing what Farrukh said, I'll be getting ovals and rectangles that are using the same variables, meaning that they will be within each other. Thanks for your help, I found another way to solve my problem, now it gerenates independent ovals and rectangles
ovals = new MyOval[ 5 + randomNumbers.nextInt(5)];
rectangles = new MyRectangle [ 5 + randomNumbers.nextInt(5)];
for (int count = 0; count <ovals.length; count++){
int x1 = randomNumbers.nextInt(300);
int y1 = randomNumbers.nextInt(300);
int x2 = randomNumbers.nextInt(300);
int y2 = randomNumbers.nextInt(300);
Color color = new Color (randomNumbers.nextInt(256), randomNumbers.nextInt(256), randomNumbers.nextInt(256));
ovals[count] = new MyOval(x1, y1, x2, y2, color);
}
for (int count = 0; count <rectangles.length; count++){
int x1 = randomNumbers.nextInt(300);
int y1 = randomNumbers.nextInt(300);
int x2 = randomNumbers.nextInt(300);
int y2 = randomNumbers.nextInt(300);
Color color = new Color (randomNumbers.nextInt(256), randomNumbers.nextInt(256), randomNumbers.nextInt(256));
rectangles[count] = new MyRectangle(x1, y1, x2, y2, color);
}

Number Line using Java Graphics API

I am trying to create a number line with labelled x-axis.Two problems:
Everything works fine for 0-9. But anything after that, the numbers get squashed together and not properly oriented on the scale.
My main axis line tends to disappear every time I try maximizing my window or at times it just wouldn't appear at all.Every time any of these happen, I have to re-compile my code and it works just fine.
Any help with the above problems will be greatly appreciated.
import java.awt.Graphics;
import javax.swing.JFrame;
/**
* #author Emil Shirima
*
*/
public class Drawing extends JFrame {
/**
* #param args
*/
int width = 300, height = 300, spacing = 10;
int x1 = 0, y1 = 150, x2 = 300, y2 = 150;
public Drawing() {
setTitle("Trial");
setSize(width, height);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
#Override
public void paint(Graphics brush) {
brush.drawLine(x1, y1, x2, y2);
x1 = 10;
y1 = 150;
x2 = 10;
y2 = 130;
// brush.drawLine(x1, y1, x2, y2);
for (int i = 0; i < 12; ++i) {
String ID = Integer.toString(i);
x1 = x2 += spacing;
brush.drawLine(x1, y1, x2, y2);
if (i < 10) {
brush.drawString(ID, x1 - 3, y2 + 40);
} else {
// With the below implementation, the numbers overlap each other
// and are not properly oriented on the axis
brush.drawString(ID, x1 - 3, y2 + 40);
// TODO: I need to resize the numbers after 10 so as they fit
// properly on the scale
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Drawing draw_object = new Drawing();
}
Current implementation:
Maximized GUI:
Your main problem:
You change x1, x2 within your paint method, and these changes will persist on the next painting. In other words, you're changing the state of the object within a rendering method, something that you must avoid doing.
You're using "magic" numbers making your program difficult to debug.
Other associated problems:
You're drawing directly in a JFrame, something that the Swing painting tutorials tell you exactly not to do since there are risks of significant side effects.
Instead draw in a JPanel's paintComponent method method.
You're not calling any super painting method, thus breaking the painting chain.
If you want the number line to extend through the component, get the component's size in the painting method (again, paintComponent) and use that to help determine the placement of the line.
Also consider sprinkling in a little FontMetrics to help place your numeric text. For example the following code creates a realizable number line:
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import javax.swing.*;
#SuppressWarnings("serial")
public class SimpleNumberLinePanel extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = 300;
private static final int GAP = 10;
private static final int START = 0;
private static final int END = 12;
private static final int VERT_LINE_HEIGHT = 20;
private static final Font FONT = new Font(Font.MONOSPACED, Font.BOLD, 14);
private static final int TEXT_GAP = 2;
#Override
protected void paintComponent(Graphics g) {
// call super method
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
// initialize these guys each time paintComponent is called
int x1 = GAP;
int y1 = height / 2;
int x2 = width - 2 * GAP;
int y2 = y1;
g.drawLine(x1, y1, x2, y2);
for (int i = START; i <= END; i++) {
int x = (i * (x2 - x1)) / (END - START) + GAP;
drawNumberAndLine(g, i, x, y1, VERT_LINE_HEIGHT);
}
}
private void drawNumberAndLine(Graphics g, int number, int x, int y,
int vertLineHeight) {
int x1 = x;
int y1 = y;
int x2 = x;
int y2 = y - vertLineHeight;
g.drawLine(x1, y1, x2, y2);
String text = String.valueOf(number);
g.setFont(FONT);
FontMetrics fontMetrics = g.getFontMetrics();
int textX = x - fontMetrics.stringWidth(text) / 2;
int textY = y + fontMetrics.getHeight() + TEXT_GAP;
g.drawString(text, textX, textY);
}
#Override // make GUI bigger
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Number Line");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new SimpleNumberLinePanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Trying code an applet that draw A SierpinskiTriangle with a for loop

Hi every one so i am trying to write a code that when I run it will draw a SierpinskiTriangle. The program has to have a for loop which i already have but i have a problem when trying to get the program to complile. it says double cannot be convert to Point2D can anyone help me with this?
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Line2D;
public class ST extends JFrame {
int N = 50000;
double sqrt3 = Math.sqrt(3);
double x = 0.0, y = 0.0;
public static void main(String args[]) {
ST t = new ST();
t.add(new JComponent() {
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
for (int i = 0; i < N; i++) {
double r = Math.random();
double x0, y0;
if (r < 1./3.) {
x0 = 0.0; y0 = 0.0;
} else if (r < 2./3.) {
x0 = 0.0; y0 = 2.0 ;
} else {
x0 = sqrt3; y0 = 1.0;
}
double x = (x0 + x) / 2;
double y = (y0 + y) / 2;
Shape l = new Line2D.Double(x,y);
g2d.draw(l);
}
}
});
t.setDefaultCloseOperation(EXIT_ON_CLOSE);
t.setSize(220, 300);
t.setVisible(true);
}
}
As the Java API at http://docs.oracle.com/javase/7/docs/api/java/awt/geom/Line2D.Double.html tells, class Line2D.Double has two constructors:
Line2D.Double(double x1, double y1, double x2, double y2)
and
Line2D.Double(Point2D p1, Point2D p2)
since you specified two parameters, the java compiler assumes the latter one.

Categories