I am having a problem with my java code. I'm trying to make it so the top left quadrant produces a set number of lines input by a user through JOption Pane which are in random colors and in random positions. The programs builds successfully but it does not produce the number of lines the user input, nor does it set a random color (This it at the very bottom of my code). Can someone please explain how to fix this problem? Thanks very much.
Edit: fixed the curve braces but still will not work.
Edit: Everything works now except the random colors
import javax.swing.*; //for JFrame
import java.awt.*; //for Graphics and Container
import java.util.Random;
import javax.swing.JOptionPane;
// other import statements here
public class RandomGraphics
{
// constants are used to draw the grid, and for you to put shapes in the grid
public static final int MIDX = 400;
public static final int MIDY = 300;
public static final int MAXX = 799;
public static final int MAXY = 599;
public static final int COLOR = (int) (Math.random() * 256);
// make another constant for the color value that will
// be used to generate a random color
public static void main( String[] args )throws InterruptedException
{
//*** This next section sets up the graphics window.
//*** You are not required to understand it
Container contentPane;
Graphics g;
JFrame win = new JFrame("Random Graphics");
win.setSize(825,650);
win.setLocation(0,0);
win.setVisible(true);
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
contentPane = win.getContentPane();
contentPane.setBackground(Color.white);
g = contentPane.getGraphics();
Thread.sleep(50);
//*** done setting up graphics window
// Draws Grid - DO NOT CHANGE
// After you use JOptionPane to get the number of lines, you can move this
// section of code to just after that, so the lines will not disappear
g.drawRect(0,0,MAXX+1,MAXY+1);
g.drawLine(0,MIDY,MAXX,MIDY); // horizontal line
g.drawLine(MIDX,0,MIDX,MAXY); // vertical line
// Create Random object
Random r = new Random();
// Top left quadrant:
// Use a JOptionPane to ask the user to enter the number of lines 1 to 100.
int count = 0;
do
{
String morelines = JOptionPane.showInputDialog("Enter a number of lines between 1 to 100");
count = Integer.parseInt(morelines);
}
while(count > 100 || count < 1);
for(int i = 1; i >= count; i++)
{
g.setColor(new Color (r.nextInt(COLOR), r.nextInt(COLOR), r.nextInt(COLOR)));
g.drawLine(r.nextInt(MIDX), r.nextInt(MIDY), r.nextInt(MIDX), r.nextInt(MIDY));
}
g = contentPane.getGraphics();
Graphics objects are not persistent, the programmer needs to draw the GUI to them when asked to do so. For tips, see the Performing Custom Painting Lesson of the tutorial.
Beside the 'always include curly braces around loops advice', note..
for(int i = 1; i >= count; i++)
Should be..
for(int i = 1; i <= count; i++)
But don't ignore the advice about custom painting. The app. will not render reliably until that is fixed.
for(int i = 1; i >= count; i++)
g.setColor(new Color (r.nextInt(COLOR), r.nextInt(COLOR), r.nextInt(COLOR)));
g.drawLine(r.nextInt(MIDX), r.nextInt(MIDY), r.nextInt(MIDX), r.nextInt(MIDY));
Looking at your indenting, it looks like you want g.setColor(...) and g.drawLine(...) to be inside your for loop. You need to enclose them in curly braces {}, otherwise only the statement immediately following your for loop will be inside the loop.
Related
Back again with another problem that has stumped me completely and cannot for the life of me fix.
So I had previously posted a question about my Java game I am making for a class that with the help of #MadProgrammer was fixed...mostly. Now there is a new problem that needs a post all to it's own
Previous Post:
Rows and columns with multidimensional array java
Problem:
In the code below I have it set up to loop through the variables x and y to make rows and columns on a jPanel. Each time it loops through it should randomly mark the "x,y" location with one of the "terrains" so that later it can "paint" that location with the appropriate colored 20x20 square.
The code runs great except for one thing, it looks like it skips the very first "if statement" that marks the "terran[0]" which is "floor". When the code is ran it "paints" the other three "terrains" and not a single "floor" "terrain".
I have looked for a solution on these posts but no success:
Java if statement is skipped
If statement being skipped during execution
Java - for loops being skipped
Java if-statement being skipped
Here is a working piece of code that results in the problem at hand:
import java.awt.*;
import javax.swing.*;
import java.util.*;
public class gamePanel extends JPanel
{
public gamePanel()
{
setBounds(115,93,480,480);
}
private Random generator = new Random();
int floor = 0; //initializes the variable floor to zero for later use
int dirt = 1;
int stone = 2;
int water = 3;
int width = 24;
int height = 24;
int x, y; // my x & y variables for coordinates
int[][] coords = new int[width][height]; //my array that I want to store the coordinates for later use in painting
int[] terrain = {floor, dirt, stone, water}; //my terrain that will determine the color of the paint
public void mapGen() //what should mark/generate the JPanel
{
for(x = 0; x < width; x++)
{
for(y = 0; y < height; y++)
{
int z = generator.nextInt(20);// part of the randomization
if(z <= 10)
{
coords[x][y] = terrain[0]; //should mark the coordinates as floor
}
if(z == 11)
{
coords[x][y] = terrain[3];//should mark the coordinates as water
}
if(z >= 12 && z <= 16)
{
coords[x][y] = terrain[2];//should mark the coordinates as stone
}
if(z >= 17 && z <= 19)
{
coords[x][y] = terrain[1];//should mark the coordinates as dirt
}
coords[0][0] = terrain[0]; // sets coordinate 0,0 to floor //need to have these always be floor
coords[23][23] = terrain[0]; // sets coordinate 24,24 to floor //^^^^^^^^^^
}
}
}
#Override
public void paintComponent(Graphics g)//what will paint each 20x20 square on the grid what it is assigned
{
super.paintComponent(g);
for(int x = 0; x < width; x++)
{
for(int y = 0; y < height; y++)
{
mapGen();
if(coords[x][y] == terrain[floor])//should paint the floor color at marked coordinates
{
g.setColor(Color.white);
g.fillRect((x*20), (y*20), 20, 20);
}
if(coords[x][y] == terrain[dirt]);//should paint the dirt color at marked coordinates
{
g.setColor(new Color(135,102,31));
g.fillRect((x*20), (y*20), 20, 20);
}
if(coords[x][y] == terrain[stone])//should paint the stone color at marked coordinates
{
g.setColor(new Color(196,196,196));
g.fillRect((x*20),(y*20),20,20);
}
if(coords[x][y] == terrain[water])//should paint the water color at marked coordinates
{
g.setColor(new Color(85,199,237));
g.fillRect((x*20),(y*20),20,20);
}
}
}
}//end paintComponent
public static void main(String[] args)
{
gamePanel panel = new gamePanel();
JFrame frame = new JFrame();
frame.setSize(500,550);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(panel);
frame.setVisible(true);
}//end main
}// end gamePanel
Please keep in mind that I am a novice programmer and I am still learning. So anything that is not considered "basic" code please explain in detail.
I posted this question a bit earlier and was told to make it SSCCE so here goes (if I can make any improvements feel free to let me know):
I'm wondering why when my button "confirm" is clicked the old squares disappear and the redrawn squares do not appear on my GUI (made with swing). The Squares class draws 200 spaced out squares with an ID (0, 1, 2, or 3 as String) inside obtained from a different class (for the purpose of this question, let's assume it is always 0 and not include that class). For clarification: Squares draws everything perfectly the first time (also retrieves the correct IDs), but I want it to redraw everything once the button is clicked with new IDs.
Code for Squares:
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.util.ArrayList;
public class Squares extends JPanel{
private ArrayList<Rectangle> squares = new ArrayList<Rectangle>();
private String stringID = "0";
public void addSquare(int x, int y, int width, int height, int ID) {
Rectangle rect = new Rectangle(x, y, width, height);
squares.add(rect);
stringID = Integer.toString(ID);
if(ID == 0){
stringID = "";
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
FontMetrics fm = g2.getFontMetrics();
int fontAscent = fm.getAscent();
g2.setClip(new Rectangle(0,0,Integer.MAX_VALUE,Integer.MAX_VALUE));
for (Rectangle rect : squares) {
g2.drawString(stringID, rect.x + 7, rect.y + 2 + fontAscent);
g2.draw(rect);
}
}
}
Code for GUI:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GUIReserver extends JFrame implements Runnable{
private int myID;
private JButton confirm = new JButton("Check Availability and Confirm Reservation");
private JFrame GUI = new JFrame();
private Squares square;
public GUIReserver(int i) {
this.myID = i;
}
#Override
public void run() {
int rows = 50;
int seatsInRow = 4;
confirm.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
GUI.getContentPane().remove(square);
square = new Squares();
int spaceNum = 0;
int rowNum = 0;
int offsetX = 200;
int offsetY = 0;
for(int i = 0; i < rows * seatsInRow; i++){
square.addSquare(rowNum * 31 + offsetX,spaceNum * 21 + 50 + offsetY,20,20, 0); //normally the 4th parameter here would retrieve the ID from the main class
rowNum++;
if(rowNum == 10){
rowNum = 0;
spaceNum++;
}
if(spaceNum == 2){
spaceNum = 3;
rowNum = 0;
}
if(spaceNum == 5){
spaceNum = 0;
offsetY += 140;
}
}
GUI.getContentPane().add(square); //this does not show up at all (could be that it wasn't drawn, could be that it is out of view etc...)
GUI.repaint(); //the line in question
}
});
GUI.setLayout(new FlowLayout());
GUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GUI.setLocation(0,0);
GUI.setExtendedState(JFrame.MAXIMIZED_BOTH);
square = new Squares();
int spaceNum = 0;
int rowNum = 0;
int offsetX = 200;
int offsetY = 0;
for(int i = 0; i < rows * seatsInRow; i++){
square.addSquare(rowNum * 31 + offsetX,spaceNum * 21 + 50 + offsetY,20,20, 0); //normally the 4th parameter here would retrieve the ID from the main class
rowNum++;
if(rowNum == 10){
rowNum = 0;
spaceNum++;
}
if(spaceNum == 2){
spaceNum = 3;
rowNum = 0;
}
if(spaceNum == 5){
spaceNum = 0;
offsetY += 140;
}
}
GUI.getContentPane().add(square); //this shows up the way I wish
GUI.add(confirm);
GUI.pack();
GUI.setVisible(true);
}
}
Code for main:
public class AircraftSeatReservation {
static AircraftSeatReservation me = new AircraftSeatReservation();
private final int rows = 50;
private final int seatsInRow = 4;
private int seatsAvailable = rows * seatsInRow;
private Thread t3;
public static void main(String[] args) {
GUIReserver GR1 = new GUIReserver(3);
me.t3 = new Thread(GR1);
me.t3.start();
}
}
One major problem: Your Squares JPanels preferred size is only 20 by 20, and will likely actually be that size since it seems to be added to a FlowLayout-using container. Next you seem to be drawing at locations that are well beyond the bounds of this component, and so the drawings likely will never be seen. Consider allowing your Squares objects to be larger, and make sure to only draw within the bounds of this component.
Note also there is code that doesn't make sense, including:
private int myID;
private JTextField row, column, instru draft saved // ???
package question2;ction1, instruction2, seatLabel, rowLabel; // ???
I'm guessing that it's
private int myID;
private JTextField row, column, instruction1, instruction2, seatLabel, rowLabel;
And this won't compile for us:
int rows = AircraftSeatReservation.getRows();
int seatsInRow = AircraftSeatReservation.getSeatsInRow(); // and shouldn't this take an int row parameter?
since we don't have your AircraftSeatReservation class (hopefully you don't really have static methods in that class).
And we can't compile or run your current code. We don't want to see your whole program, but rather you should condense your code into the smallest bit that still compiles, has no extra code that's not relevant to your problem, but still demonstrates your problem. So as Andrew Thompson recommends, for better help, please create and post your Minimal, Complete, and Verifiable example or Short, Self Contained, Correct Example.
I would try to OOP-ify your problem as much as possible, to allow you to divide and conquer. This could involve:
Creating a SeatClass enum, one with possibly two elements, FIRST and COACH.
Creating a non-GUI Seat class, one with several fields including possibly: int row, char seat ( such as A, B, C, D, E, F), a SeatClass field to see if it is a first class seat or coach, and a boolean reserved field that is only true if the seat is reserved.
This class would also have a getId() method that returns a String concatenation of the row number and the seat char.
Creating a non-GUI Airplane class, one that holds two arrays of Seats, one for SeatClass.FIRST or first-class seats, and one for SeatClass.COACH.
It would also have a row count field and a seat count (column count) field.
After creating all these, then work on your GUI classes.
I'd create a GUI class for Seats, perhaps GuiSeat, have it contain a Seat object, perhaps have it extend JPanel, allow it to display its own id String that it gets from its contained Seat object, have it override getBackground(...) so that it's color will depend on whether the seat is reserved or not.
etc.....
So the crux of my problem is plotting multiple components into one JFrame in Java. I'm trying to use the same component twice to plot two different lines, but only one appears. I'm working across three separate classes in separate files, which might be making it more difficult for me. I have tried possible solutions to no avail here, here, here, here, and elsewhere. I suspect I am doing multiple things wrong, as I'm still trying to fully understand JFrame, JPanel, and LayoutManagers. Can anyone show where I went wrong?
My tester class is as follows:
import javax.swing.JFrame;
public class TransportSlabTester
{
public static void main(String[] args)
{
System.out.println("Estimation at 100 sections: ");
TransportSlab slab1 = new TransportSlab(10000,1,5,100);
System.out.println();
JFrame frame = new JFrame("Attenuated Profile");
frame.setSize(600,600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TransportSlabGraph component = new TransportSlabGraph();
//analytical is a method from a 3rd class that returns double[]
component.attProfileArray(slab1.analytical(),slab1.getThickness());
frame.add(component);
component = new TransportSlabGraph();
//euler is a method from a 3rd class that returns double[]
component.attProfileArray(slab1.euler(),slab1.getThickness());
frame.add(component);
frame.setVisible(true);
}
}
Now, the class that extends JPanel:
import java.awt.*;
import java.awt.geom.Line2D;
import java.math.*;
import javax.swing.JPanel;
public class TransportSlabGraph extends JPanel
{
double[] N, xAxes, yAxes;
final int edge = 100; //Distance from edge of frame
String[] xlabel = new String[11];
String[] ylabel = new String[11];
/**
*
* #param inputN Data array of type {#code double[]}
* #param thickness Thickness set by the original constructor
*/
public void attProfileArray(double[] inputN, double thickness)
{
N = new double[inputN.length];
//Create labels for the tick marks of the x and y axis from rounded #'s
BigDecimal bd1, bd2;
for (int i = 0; i <= 10; i++)
{
bd1 = new BigDecimal((thickness/10)*i);
MathContext mc = new MathContext(2); //Round to one decimal place
bd2 = bd1.round(mc);
xlabel[i] = String.valueOf(bd2.doubleValue());
ylabel[i] = String.valueOf((inputN[0]*i)/(inputN.length-1));
}
//Set up data array and the axes
for (int i = 0; i < N.length; i++)
{
N[i]=inputN[i];
xAxes = new double[N.length];
yAxes = new double[N.length];
}
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
//Get frame dimensions to scale drawn components
int w = getWidth();
int h = getHeight();
double xInc = (double)(w-2*edge)/(N.length-1);
double scale = (double)(h-2*edge)/N[0];
g2.draw(new Line2D.Double(edge, h-edge, w-edge, h-edge)); //draw x axis
g2.draw(new Line2D.Double(edge, edge, edge, h-edge)); // draw y axis
//Create evenly spaced tick marks for both axes and label them
for (int i = 0; i <= 10; i++)
{
g2.draw(new Line2D.Double(edge+((w-edge-edge)/10.0)*i, h-edge-10, edge+((w-edge-edge)/10.0)*i, h-edge+10)); //x ticks
g2.draw(new Line2D.Double(edge-10, h-edge-((h-edge-edge)/10.0)*i, edge+10, h-edge-((h-edge-edge)/10.0)*i)); //y ticks
g2.drawString(xlabel[i],(int)(edge+((w-edge-edge)/10.0)*i),h-edge+20);
g2.drawString(ylabel[i],edge-30,(int)(h-edge-((h-edge-edge)/10.0)*i));
}
//Scale data and convert to pixel coordinates
for (int i = 0; i < N.length; i++)
{
xAxes[i] = edge+i*xInc;
yAxes[i] = h-edge-scale*N[i];
}
//Only set the data line's color
g2.setPaint(Color.BLUE);
//Draw the data as a series of line segments
for (int i = 1; i < N.length; i++)
{
g2.draw(new Line2D.Double(xAxes[i-1],yAxes[i-1],xAxes[i],yAxes[i]));
}
}
}
Problem #1
An instance of a Component may only reside within a single Container (once).
You will need to create a new instance of each Component you want to add. I would recommend a factory pattern...
Problem #2
JFrame, but default, uses a BorderLayout, which will only allow a single component to reside at each of it's 5 available layout positions.
You will also have problems because your TransportSlabGraph class doesn't override it's getPreferredSize method, which means that, by default, instance of the component will be provided with a default size of 0x0 by many of the layout managers.
Consider changing the layout manager to something like GridLayout to start with.
Take a look at Laying Out Components Within a Container for more details
I am trying to diffuse a color in java Draw (which doesn't have the capability to diffuse normally) but I ran into an error and I can't seem to spot it.
The way I went about diffusing was by writing a small script that would draw my shape hundreds of times, each time smaller and slightly varying in color. This is my snippet:
import javax.swing.*;
import java.awt.*;
public class DiffuseDraw extends JFrame
{
//set size of window here
final int length = 350;
final int height = 370;
public DiffuseDraw()
{
super("Graphics Project Window");
Container container = getContentPane();
setBackground(new Color(0,0,0));
setSize(length, height);
setVisible(true);
}
// my problem comes here:
public void paint(Graphics g)
{
Draw.fillRectangle(g,0,0,length,height,new Color(19,24,32));
int rad = 325; // size of the biggest circle
float floatGreen = 0; // Color components for black
float floatBlue = 0;
float floatRed = 0;
int counter = 0; // the counter
while (counter < 290) {
rad = rad - 1; // Here we shrink the by a small incriment
floatRed = floatRed + 87/290; //red component slowly goes brighter
floatBlue = floatBlue + 178/290; // blue component slowly goes brighter
floatGreen = floatGreen + 211/290; // green component slowly goes brighter
int intRed = (int)Math.round(floatRed);
int intBlue = (int)Math.round(floatBlue);
int intGreen = (int)Math.round(floatGreen);
Draw.fillCircle(g,173,307,rad,new Color(intRed,intBlue,intGreen));
counter = counter + 1;
}
}
public static void main(String args[]) {
DiffuseDraw prog = new DiffuseDraw();
prog.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
When I compile and run, I only get a black screen. I am guessing that the problem is coming from the colors not changing. The number I am adding the float red blue and green by came from me wanting to diffuse a type of blue, so I took the the brightest color of blue that would appear and divided it by 290, the number of times the loop would run.
Instead of
87/290, 178/290, and 211/290,
try using
(float)87/290, (float)178/290, and (float)211/290.
That will, at least, add some color to the window- the problem is that by default, a number like 87/290 will be evaluated to 0; casting it to a float will give the desired result of 0.3 instead.
The code below will produce randomly generated circles of different colors. I need to be able to specify the color of the circle by it's size so that the loop will produce the same pattern of circles in different locations. This needs to be done with a 2d array. I know this is probably not that difficult, but I can't seem to grasp the concept.
Here are the directions and my code.
Thanks!
Set up a 2-D, int colors[][], array with 6 rows, one for each circle, and 3 columns, one for each element (Red, Green, Blue) of the colors to be used. In the above display the color values were randomly generated in the range 0 to 255 at the beginning of the program. Then for each diameter[i], color[i][0], color[i][1] and color[i][2] were used for the RGB levels.
import java.io.*;
import java.util.*;
import java.awt.*;
public class Lab10 {
/**
* #param args
*/
public static void main(String[] args) {
Scanner console=new Scanner (System.in);
Random r = new Random();
int [] color= new int [3];
color[0]=r.nextInt(256);
color[1]=r.nextInt(256);
color[2]=r.nextInt(256);
System.out.println("Please enter 6 integer values. The values should be in descending order and in the range 100 to 1.");
int[] diameters=new int[6];
int colors[][] = new int [6][3];
for(int i=0; i<6; i++){
diameters[i]=console.nextInt();//values entered
}
for (int i=0; i<diameters.length; i++) {
for (int j = 0; j < color.length; j++) {
colors[i][j]=colors[i][j];
}
}
int panelX = 400, panelY = 400;
DrawingPanel panel = new DrawingPanel(panelX, panelY);
panel.setBackground(Color.WHITE);
Graphics g = panel.getGraphics();
for (int i=0; i<10; i++){
int centerX=r.nextInt(350);
int centerY=r.nextInt(350);
for(int value:diameters){
g.setColor(new Color(r.nextInt(256),r.nextInt(256), r.nextInt(256)));
g.fillOval(centerX - value , centerY - value, 2 * value, 2 * value);
}
}
}
}
Hint
To break the concept for you.
int color[6][3] is your array.
To randomly generate the color values
create an object of class Random
Random random = new Random();
Do a loop on rows of color
for(int i=0;i<6;i++)
{
for(int j=0;j<3;j++)
color[i][j]= random.nextInt(255);
}
Now draw the circle like for diameter[i] ,
refer to color[i][0],color[i][1],color[i][2] for its rgb values
So if I got this right, you want to draw circles randomly, and you want the color to be dependent on diameter.
Here is my solution to that problem: pastebin
Also, i tried to show how it can be done both with and without java 8, so don't be confused about it.
Here is how it should look like: