I'm trying to write the game of life. However, no matter how hard I try, I can't seem to add Cell components onto the frame with the buttons. They do appear if I make a new frame and add them, but even so, I can't seem to add more than one component.
So I how I add the components to the frame with all the stuff on it and how do I add multiple components?
Thanks!
Here's my code:
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class Visuals extends JFrame implements ActionListener{
private static Board b;
private GameOfLife g;
private JButton nextGen;
private JButton random;
public Visuals(Board b){
super("The Game of Life");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel=new JPanel();
nextGen = new JButton("Next Generation");
panel.add(nextGen);
nextGen.addActionListener(this);
random = new JButton("Random");
panel.add(random);
random.addActionListener(this);
this.add(panel);
this.setSize(800, 700);
this.setVisible(true);
/*for(int i=0, yShift=80; i<b.getRow(); i++, yShift+=20){
for (int j=0, xShift=30; j<b.getCol(); j++, xShift+=20){
Cell c= new Cell(xShift,yShift,i,j);
this.add(c);
}
}*/
Cell c= new Cell(100,100,1,1);
Cell d= new Cell(200,200,1,1);
this.add(c);
this.add(d);
JFrame frame=new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 700);
frame.setVisible(true);
frame.add(c);
frame.add(d);
}
public void paint(Graphics g){
super.paint(g);
for(int i=0, yShift=80; i<b.getRow(); i++, yShift+=20){
for (int j=0, xShift=30; j<b.getCol(); j++, xShift+=20){
if(b.getSpot(i, j)==1){
g.setColor(Color.red);
g.fillRect(xShift, yShift, 10, 10);
}
else{
g.setColor(Color.white);
g.fillRect(xShift, yShift, 10, 10);
}
}
}
}
public static void main(String[] cnbe){
b= new Board (30,30);
Visuals v = new Visuals(b);
}
public void actionPerformed(ActionEvent event) {
Object cause = event.getSource();
if(cause == nextGen){
GameOfLife g=new GameOfLife(b);
g.nextGeneration();
System.out.println(g);
this.repaint();
}
if(cause == random){
GameOfLife g=new GameOfLife(b);
g.random();
System.out.println(g);
this.repaint();
}
}
public class Cell extends JComponent{
int row;
int col;
int x;
int y;
Rectangle r;
public Cell(int x, int y, int row, int col){
r= new Rectangle(x,y,10,10);
this.row=row;
this.col=col;
this.x=x;
this.y=y;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString("DRAW ME",200,200);
Graphics2D g2= (Graphics2D) g;
g2.setColor(Color.green);
r= new Rectangle(x,y,100,100);
g2.fill(r);
/*if(b.getSpot(row, col)==1){
g.setColor(Color.red);
g.fillRect(x, y, 10, 10);
}
else{
g.setColor(Color.white);
g.fillRect(x, y, 10, 10);
}*/
}
class MousePressListener implements MouseListener{
public void mousePressed(MouseEvent event) {
/*int x= event.getX();
int y= event.getY();
if(x>r.getX() && x<r.getX()+10 && y>r.getY() && y<r.getY()+10){
if(b.getSpot(row, col)==1){
b.setSpot(row, col, 0);
repaint();
}
else{
b.setSpot(row, col, 1);
repaint();
}
}*/
}
public void mouseReleased(MouseEvent arg0) {
}
public void mouseClicked(MouseEvent arg0) {
}
public void mouseEntered(MouseEvent arg0) {
}
public void mouseExited(MouseEvent arg0) {
}
}
}
}
You have an issue with Layout Managers. Each time you add a component to the JFrame you overwrite what was already there. I'm not too familiar with Game of Life, but I don't think you want your cells to be JComponents. You can represent your board as an array of booleans, representing the alive and dead state, so your Visual constructor becomes:
public Visuals(Board b) {
super("The Game of Life");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container container = getContentPane(); // 1
JPanel panel = new JPanel(new FlowLayout()); // 2
nextGen = new JButton("Next Generation");
panel.add(nextGen);
nextGen.addActionListener(this);
random = new JButton("Random");
panel.add(random);
random.addActionListener(this);
container.add(panel); // 3
setSize(800, 700);
setVisible(true);
}
In your Board class you would represent the board as an array:
public class Board{
private boolean[][] board;
public Board(int x, int y) {
board = new boolean[x][y];
}
}
Then in the nextGeneration method of your GameOfLife class, perform whatever calculations you're doing and set the true/false (or alive/dead) state of the positions on the Board.
Your Visuals.paint method then becomes something like:
public void paint(Graphics g) {
super.paint(g);
for (int i = 0, yShift = 80; i < b.getRow(); i++, yShift += 20) {
for (int j = 0, xShift = 30; j < b.getCol(); j++, xShift += 20) {
if (b.isAlive(i, j)) {
g.setColor(Color.red);
g.fillRect(xShift, yShift, 10, 10);
} else {
g.setColor(Color.white);
g.fillRect(xShift, yShift, 10, 10);
}
}
}
}
iaAlive is just returning the value of the board array at that position:
public boolean isAlive(int i, int j) {
return board[i][j];
}
But like I say, I'm not familiar with the game.
Related
I am having a problem with my code, if I click on rectangle and do the mouse clicks on the screen it will show the shape and it works fine.. but if I clicked on the circle after that, all the rec
tangles that have been stored stays on same location but changes to circle. how can I prevent the shapes that have been stored from changing?
First Class:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class MouseClick implements ActionListener{
private static int x,y;
private static DrawingObjects object = new DrawingObjects();
JPanel panel = new JPanel();
JFrame frame = new JFrame("MouseClick");
MouseClick(){
dObjects();
}
void dObjects() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout(2,2));
frame.add(object);
frame.add(panel);
panel.setBackground(Color.WHITE);
panel.setSize(10, 300);
panel.setLocation(100, 200);
panel.setLayout(new GridLayout(1,2));
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setSize(400, 400);
object.addMouseListener(new AL());
Button rect = new Button("Rectangle");
Button oval = new Button("Circle");
panel.add(rect);
panel.add(oval);
rect.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
object.setType(1);
}
});
oval.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
object.setType(2);
}
}); }
public static void main(String[] args){
new MouseClick();
}
static class AL extends MouseAdapter{
public void mouseClicked (MouseEvent e){
x = e.getX();
y = e.getY();
object.drawing(x, y);
}
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
}
Second Class:
import javax.swing.*;
import javafx.scene.input.MouseEvent;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.*;
public class DrawingObjects extends JPanel{
private ArrayList<Point> points = new ArrayList<>();
public int shapetype ;
public void drawing(int x, int y){
points.add(new Point(x, y));
repaint();
}
public void setType(int choice){
if(choice==1){
shapetype = 1;
}
else if (choice ==2){
shapetype = 2;
}
}
public void paintComponent(Graphics g){
super.paintComponent(g);
if(shapetype == 1){
for(Point p : points){
g.fillRect(p.x, p.y, 60, 20);
g.setColor(Color.GREEN);
repaint();
}
}
else if (shapetype == 2){
for(Point p : points){
g.fillOval(p.x, p.y, 20, 20);
g.setColor(Color.RED);
repaint();
}
}
}
}
The problem occurs because the shapetype is not stored along with the points on which the shapes are drawn. As a result, within the paintComponent method, when all shapes in locations stored in points array get redrawn, they use the current value of shapetype. Not the value of shapetype when the shape was created for the first time.
A simple (yet not the best) solution, with minimum code change would be to store the shapetype as follows.
In DrawingObjects class, add another array to store the shapetype.
private ArrayList<Integer> shapeTypes = new ArrayList<>();
Update the drawing method as follows to store the current shapetype along with the point.
public void drawing(int x, int y) {
points.add(new Point(x, y));
shapeTypes.add(shapetype);
repaint();
}
Refer the stored shapetype when repainting the shapes as follows.
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < points.size(); i++) {
Point p = points.get(i);
if (shapeTypes.get(i) == 1) {
g.fillRect(p.x, p.y, 60, 20);
g.setColor(Color.GREEN);
repaint();
} else if (shapeTypes.get(i) == 2) {
g.fillOval(p.x, p.y, 20, 20);
g.setColor(Color.RED);
repaint();
}
}
}
A better design would be to create a separate class with the capability to store the location as well as the shape type with the implementation on how it should be painted.
I am trying to make a program that work like this:
In Window class every time I click on the button, the method panel2 of Panel is called: first it is drawing a first circle, then a second one (after the time defined in the timer). Then, I click again on the button, and it is drawing a fist circle, then a second one then a third one. etc.
The problem is that it when I click to obtain 3 circles appearing one after the other, the two first circles drawn at the previous step (before I pressed a second time the button) stay on the screen and only the third circle is drawn when i press the button (instead of having : first circle drawn, second circle drawn, third circle drawn). I hope I am clear.
Here is a simple code:
Window
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Window extends JFrame implements ActionListener{
int h = 2;
Panel b = new Panel();
JPanel container = new JPanel();
JButton btn = new JButton("Start");
JButton bouton = new JButton();
Panel boutonPane = new Panel();
public Window(){
this.setTitle("Animation");
this.setSize(300, 300);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
container.setBackground(Color.white);
container.setLayout(new BorderLayout());
JPanel top = new JPanel();
btn.addActionListener(this);
top.add(btn);
container.add(top);
this.setContentPane(container);
this.setVisible(true);
}
public void window2(){
this.setTitle("ADHD");
this.setSize(1000,700);
this.setLocationRelativeTo(null);
if (h < 11){
boutonPane.panel2(h);
bouton.addActionListener(this);
boutonPane.add(bouton);
this.add(boutonPane);
this.setContentPane(boutonPane);
updateWindow2();
}
this.setVisible(true);
}
public void updateWindow2(){
boutonPane.panel2(h);
this.revalidate();
this.repaint();
}
public void actionPerformed(ActionEvent e){
if ((JButton) e.getSource() == btn){
System.out.println("pressed0");
window2();
}
if ((JButton) e.getSource() == bouton){
h++;
System.out.println("pressed" + h);
updateWindow2();
}
}
public static void main(String[] args){
Window w = new Window();
}
}
Panel
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Panel extends JPanel implements ActionListener{
int m;
int u=0;
int lgi, lrgi;
int [] ta;
Timer timer1 = new Timer(300, this);
Panel(){
}
public void panel2(int n){
m=n;
ta = new int [n];
for(int it=0; it<m;it++){
ta[it]=100*it;
}
timer1.start();
}
public void paintComponent(Graphics gr){
super.paintComponent(gr);
gr.setColor(Color.red);
for(int i=0;i<m;i++){
gr.fillOval(ta[i],ta[i], 150, 150);
}
}
#Override
public void actionPerformed(ActionEvent arg0) {
if(u<m){
u++;
revalidate();
repaint();
}
}
}
Your code needs use two int values to decide how many circles to draw and when:
The first int should be the count of current circles to draw, say called, currentCirclesToDraw.
The second int will be the number of circles to draw total.
If you use a List<Ellipse2D> like I suggest, then this number will be the size of the list. So if the List is called ellipseList, then the 2nd number will be ellipseList.size().
The first variable will be incremented in the timer up to the size of the list, but no larger, and will be used by paintComponent method to decide how many circles to draw.
Key point here: the first number, the currentCirclesToDraw, must be re-set to 0 when the button is pressed. This way your paintComponent method will start out drawing 0 circles, then 1, then 2, ...
For example, the paintComponent method could look like so:
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(CIRCLE_COLOR);
for (int i = 0; i < currentCirclesToDraw && i < ellipseList.size(); i++) {
g2.fill(ellipseList.get(i));
}
}
I use the second term in the for loop conditional statement, i < currentCirclesToDraw && i < ellipseList.size() as an additional fail-safe to be sure that we don't try to draw more circles then we have in our list.
My Timer's ActionListener would increment the currentCirclesToDraw variable and call repaint. It would stop the Timer once currentCirclesToDraw reaches the size of the ellipseList:
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (currentCirclesToDraw < ellipseList.size()) {
currentCirclesToDraw++;
repaint();
} else {
// stop the Timer
((Timer)e.getSource()).stop();
}
}
}
And my button's actionPerformed method would reset currentCirclesToDraw to 0, would add a new Ellipse2D to my ellipseList (if we've not yet reached the MAX_CIRCLE_INDEX), would call repaint() to clear the JPanel, and would construct and start the Timer:
public void actionPerformed(java.awt.event.ActionEvent arg0) {
currentCirclesToDraw = 0; // this is key -- reset the index used to control how many circles to draw
if (ellipseList.size() < MAX_CIRCLE_INDEX) {
double x = (ellipseList.size()) * CIRCLE_WIDTH / Math.pow(2, 0.5);
double y = x;
double w = CIRCLE_WIDTH;
double h = CIRCLE_WIDTH;
ellipseList.add(new Ellipse2D.Double(x, y, w, h));
}
repaint(); // clear image
new Timer(TIMER_DELAY, new TimerListener()).start();
};
Edit 3/30/14
Note it all can be put together like this:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
/**
* http://stackoverflow.com/a/22714405/522444
* http://stackoverflow.com/questions/22712655/repaint-in-panel-method-not-updated
* #author Pete
*
*/
#SuppressWarnings("serial")
public class TimerCircles extends JPanel {
private static final int PREF_W = 1000;
private static final int PREF_H = 700;
private static final Color CIRCLE_COLOR = Color.RED;
public static final int MAX_CIRCLE_INDEX = 11;
public static final int TIMER_DELAY = 300;
public static final int CIRCLE_WIDTH = 100;
private final List<Ellipse2D> ellipseList = new ArrayList<>();
private int currentCirclesToDraw = 0;
public TimerCircles() {
add(new JButton(new ButtonAction("New Circle", KeyEvent.VK_C)));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(CIRCLE_COLOR);
for (int i = 0; i < currentCirclesToDraw && i < ellipseList.size(); i++) {
g2.fill(ellipseList.get(i));
}
}
private class ButtonAction extends AbstractAction {
public ButtonAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
public void actionPerformed(java.awt.event.ActionEvent arg0) {
currentCirclesToDraw = 0; // this is key -- reset the index used to control how many circles to draw
if (ellipseList.size() < MAX_CIRCLE_INDEX) {
double x = (ellipseList.size()) * CIRCLE_WIDTH / Math.pow(2, 0.5);
double y = x;
double w = CIRCLE_WIDTH;
double h = CIRCLE_WIDTH;
ellipseList.add(new Ellipse2D.Double(x, y, w, h));
}
repaint(); // clear image
new Timer(TIMER_DELAY, new TimerListener()).start();
};
}
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (currentCirclesToDraw < ellipseList.size()) {
currentCirclesToDraw++;
repaint();
} else {
// stop the Timer
((Timer)e.getSource()).stop();
}
}
}
private static void createAndShowGui() {
TimerCircles mainPanel = new TimerCircles();
JFrame frame = new JFrame("TimerCircles");
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();
}
});
}
}
I am making a flappy bird like plane game, and in one class I have the background that moves, and then I add it to the jPanel in the main which is in its own class, in another class I have the player and I add that to the main Jpanel. But whichever class I add first dissapears when I add the second class to the JPanel. Here is my background class:
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.Timer;
public class map1 extends JPanel implements ActionListener{
Timer t = new Timer(5, this);
int rect1x = 1000, rect1y = 0;
int rect2x = 1250, rect2y = 0;
int rect3x = 1500, rect3y = 0;
int rect4x = 1750, rect4y = 0;
int rect5x = 2000, rect5y = 0;
int rect1dx = 1000, rect1dy = 300;
int rect2dx = 1250, rect2dy = 350;
int rect3dx = 1500, rect3dy = 400;
int rect4dx = 1750, rect4dy = 350;
int rect5dx = 2000, rect5dy = 300;
public map1(){t.start();}
public void rectset1(Graphics g){
g.drawRect(rect1x, rect1y, 50, 100);
g.drawRect(rect1dx, rect1dy, 50, 300);
}
public void rect2(Graphics g){
g.drawRect(rect2x, rect2y, 50, 150);
g.drawRect(rect2dx, rect2dy, 50, 300);
}
public void rect3(Graphics g){
g.drawRect(rect3x, rect3y, 50, 200);
g.drawRect(rect3dx, rect3dy, 50, 300);
}
public void rect4(Graphics g){
g.drawRect(rect4x, rect4y, 50, 150);
g.drawRect(rect4dx, rect4dy, 50, 300);
}
public void rect5(Graphics g){
g.drawRect(rect5x, rect5y, 50, 100);
g.drawRect(rect5dx, rect5dy, 50, 300);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
rectset1(g);
rect2(g);
rect3(g);
rect4(g);
rect5(g);
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
rect1x--;
rect2x --;
rect3x --;
rect4x --;
rect5x --;
rect1dx --;
rect2dx --;
rect3dx --;
rect4dx --;
rect5dx --;
}
}
And here is my plane class:
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
import javax.swing.Timer;
public class player extends JPanel implements ActionListener, KeyListener {
int x = 200, y = 300;
Timer t = new Timer(5, this);
public void space(){
y+=20;
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawOval(x, y, 50, 50);
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if(code == KeyEvent.VK_SPACE){space();}
}
#Override
public void keyReleased(KeyEvent e) {
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
y--;
}
}
And lastly my main:
import javax.swing.JFrame;
#SuppressWarnings("serial")
public class testMain extends JFrame{
public testMain(){}
public static void main(String args[]){
map1 m = new map1();
player q = new player();
JFrame j = new JFrame();
j.setSize(800,600);
j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
j.add(m);
j.add(q);
j.setVisible(true);
}
}
You should have a single JPanel that paints itself by overriding paintComponent(). That JPanel class should have a reference to anything that needs to be drawn. From the paintComponent() method, you just iterate over each game object that needs to be drawn and draw it. Better yet, each game object should have a drawMe(Graphics g) method that draws itself, and your paintComponent() method can just pass its Graphics instance into each of those methods.
public class GamePanel extends JPanel{
//example GameObjects, these could be in a list
GameObject bird = new Bird();
GameObject cloud = new Cloud();
public void paintComponent(Graphics g){
bird.drawMe(g);
cloud.drawMe(g);
}
}
First off in your main class you are extending JFrame but then instantiating it as well which is redundant. You should do either of the two, not both!
Ex:
public class main extends JFrame{
public main(){
setSize(800,600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(m);
add(q);
setVisible(true);
}
}
Secondly answering your question, you should always have a single class that does all the drawing for your game. Lets call this the Board class. You could have other classes that have functions to draw, but these functions should be called in your Board class within the paintComponent() function.
Note: Also make sure to do this -
void paintComponent(Graphics g){
super.paintComponent(g);
......
g.dispose();
}
how can I keep the previous changes using repaint() and run() or is there another solution for this.
I have this code running well. This code paints 3 ovals. When I put an input for the x-coordinate at the text box, it paints/draws the new oval. However, everytime I input and change the x-coordinate at the text box, the oval just relocates. What I want to do is to retain the previous changes that I have made. For example, I get 3 ovals at start when you hit the see coordinates button then you get 4 and so on after you input and click the add coordinate button.
Here's my code:
/deleted/
Any help would be much appreciated.
[EDIT]
I'm implementing K-nearest neighbors. So far what I have made are:
1.created a gray panel of size 500x500 from (0,0)
2.gets file using browse button.
3.gets string and tokenize
4.token[0]= k-nearest, token[1]= total neighbors
5.token[2]= x-coordinate, token[3]= y-coordinate, token[4]= type of cluster and so on.
6.input x-coord and y-coord
7.compute distance between coordinates from txt file and input
8.draw shape according to minimum distance
Here's my code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.util.*;
import java.lang.Math;
public class Knn extends JFrame implements ActionListener{
JPanel grid,panel;
JLabel xlab,ylab;
JTextArea xtex,ytex,temp;
JButton cbut,fbut;
String text;
int k, ktotal, x, y,xcori,ycori;
String[] token;
int[] itoken;
boolean paint=false, paintclass=false;
double ans,xcord,ycord;
double[] dtoken,ansarray,xarray,yarray;
Map<Double, Double> anshash;
public Knn(){
super("K-Nearest Neighbor");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(600,500);
//this.pack();
this.setVisible(true);
this.setResizable(true);
this.setLayout(null);
grid= new JPanel();
grid.setBackground(Color.GRAY);
grid.setBounds(0,0,500,500);
panel= new JPanel();
//panel.setLayout(null);
panel.setBounds(500,0,100,100);
temp= new JTextArea();
xlab= new JLabel("X");
xtex= new JTextArea("",1,7);
ylab= new JLabel("Y");
ytex= new JTextArea("",1,7);
cbut= new JButton("classify");
fbut= new JButton("Browse");
panel.add(xlab);
panel.add(xtex);
panel.add(ylab);
panel.add(ytex);
panel.add(cbut);
panel.add(fbut);
this.add(grid);
this.add(panel);
fbut.addActionListener(this);
cbut.addActionListener(this);
}
public double formula(double x1, double y1, double x2, double y2){
double tmpans= Math.pow((x2-x1),2.0) + Math.pow((y2-y1),2.0);
ans= Math.sqrt(tmpans);
return ans;
}
public void actionPerformed(ActionEvent e){
if(e.getSource()==fbut){ //choose file input coordinates
JFileChooser fileChooser= new JFileChooser();
int returnVal = fileChooser.showOpenDialog(this);
if(returnVal == JFileChooser.APPROVE_OPTION){
File file = fileChooser.getSelectedFile();
try {
//output file content to text box, copy to a string
temp.read( new FileReader(file.getAbsolutePath()),null);
text= temp.getText();
}catch(IOException ex){
ex.printStackTrace();
}
}
token = text.split("\\W+");
itoken=new int[token.length];
int i=0;
for (String str : token){
itoken[i++] = Integer.parseInt(str); //convert from string to integer
}
for (i = 4; i < itoken.length; i += 3) { //x50
itoken[i-2]= itoken[i-2] * 50;
itoken[i-1]= itoken[i-1] * 50;
}
paint=true;
repaint();
}
if(e.getSource()==cbut){
solveClass();
}
}
public void paint(Graphics g){
super.paint(g);
if (paint) {
for (int i = 4; i < itoken.length; i += 3) {
x = itoken[i-2];
y = itoken[i-1];
if(itoken[i]==1)
g.fillRect(x - 5, y - 5, 10, 10);
if(itoken[i]==2)
g.fillOval(x - 5, y - 5, 10, 10);
if(itoken[i]==3)
g.drawOval(x - 5, y - 5, 10, 10);
}
}
if(paintclass){
if(anshash.get(ansarray[0])==1)
g.fillRect(xcori - 5, ycori - 5, 10, 10);
if(anshash.get(ansarray[0])==2)
g.fillOval(xcori - 5, ycori - 5, 10, 10);
if(anshash.get(ansarray[0])==3)
g.drawOval(xcori - 5, ycori - 5, 10, 10);
}
}
public void solveClass(){
String xcors= xtex.getText();
String ycors= ytex.getText();
dtoken=new double[itoken.length];
xarray=new double[itoken[1]];
yarray=new double[itoken[1]];
ansarray=new double[itoken[1]];
int j=0;
for (String str : token)
dtoken[j++] = Double.parseDouble(str); //convert from string to double
//convert to int
xcori= Integer.parseInt(xcors);
ycori= Integer.parseInt(ycors);
//convert to double
xcord= Double.parseDouble(xcors);
ycord= Double.parseDouble(ycors);
int q=0;
for (int i = 3; i < itoken.length; i += 3) {
xarray[q]= dtoken[i-1];
yarray[q]= dtoken[i];
q++;
}
for (int i = 0; i < xarray.length; i ++)
ansarray[i]= formula(xcord,ycord,xarray[i]*50,yarray[i]*50); //x50
anshash= new HashMap<Double,Double>();
int r=0;
for(int i = 4; i < itoken.length; i += 3){
anshash.put(ansarray[r], dtoken[i]);
r++;
}
Arrays.sort(ansarray); //sort
paintclass=true;
repaint();
}
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Knn knn= new Knn();
}
});
}
}
Here's the text file:
3 5
1 2 1
4 3 2
7 5 2
6 9 3
5 5 1
"However, everytime I input and change the x-coordinate at the text box, the oval just relocates. What I want to do is to retain the previous changes that I have made"
Use a List of ball objects. Here is the Ball class
public class Ball {
int x;
int y;
public Ball(int x, int y) {
this.x = x;
this.y = y;
}
public void drawball(Graphics g) {
g.fillOval(x, y, 20, 20);
}
}
Here is the JPanel class
public class BallPanel extends JPanel {
private List<Ball> balls;
#Override
protected void paintComponent(Graphics g) {
super.paintCompoent(g);
for (Ball ball: balls) {
ball.drawBall(g);
}
}
}
The basic point is to keep a data structure of the ball locations. You may also want to have getters and setters for the x and y so you can manipulate their locations.
To add more balls, all you need to do is add to the List a new Ball(...) and call repaint();
Here's a running example. Just type in an x and a y less than 500 and click the button. You will see more balls being added. You can see in the actionPerformed where I add a new Ball and the in the paintCompoent where I loop though the ball List
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class TestBall extends Frame implements ActionListener {
private JTextField enterX;
private JTextField enterY;
private JLabel labelX;
private JLabel labelY;
private JButton addBall;
private List<Ball> balls;
private BallPanel ballPanel;
public TestBall() {
balls = new ArrayList<>();
ballPanel = new BallPanel();
JPanel p1 = new JPanel();
labelX = new JLabel("Enter X");
enterX = new JTextField(6);
labelY = new JLabel("Enter Y");
enterY = new JTextField(6);
addBall = new JButton("Add Ball");
addBall.addActionListener(TestBall.this);
p1.add(labelX);
p1.add(enterX);
p1.add(labelY);
p1.add(enterY);
p1.add(addBall);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(ballPanel, BorderLayout.CENTER);
frame.add(p1, BorderLayout.PAGE_START);
frame.pack();
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
int x = Integer.parseInt(enterX.getText());
int y = Integer.parseInt(enterY.getText());
balls.add(new Ball(x, y));
ballPanel.repaint();
}
public class BallPanel extends JPanel {
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Ball ball : balls) {
ball.drawBall(g);
}
}
}
public class Ball {
int x;
int y;
public Ball(int x, int y) {
this.x = x;
this.y = y;
}
public void drawBall(Graphics g) {
g.fillOval(x, y, 20, 20);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new TestBall();
}
});
}
}
so, i'm doing breakout in java (this is not h/w, school is over)
I want to bricks to be random in color, but my bricks change color while the game is running. so right now, it looks like the bricks are lighting up!! please help!!
package main;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Random;
public class Brick {
public static final int X = 0, Y = 0, ROW_SIZE = 8, COL_SIZE = 5;
private Random random = new Random();
private ArrayList<Rectangle> arr = new ArrayList<>();
public Brick(int width, int height) {
for(int i = 0; i < COL_SIZE; i++){
for(int j = 0; j < ROW_SIZE; j++) {
Rectangle r = new Rectangle(X + (j * (width / ROW_SIZE)),
Y + (i * (height / COL_SIZE)), (width / ROW_SIZE), (height / COL_SIZE));
arr.add(r);
}
}
}
public ArrayList<Rectangle> getList(){
return arr;
}
public void setList(ArrayList<Rectangle> rects){
arr = rects;
}
public void paint(Graphics g){
for(Rectangle rect : arr){
g.setColor(new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256)));
g.fillRect(rect.x, rect.y, rect.width, rect.height);
}
}
}
package main;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class GamePanel extends JPanel implements ActionListener, KeyListener {
Player player = new Player();
Ball ball = new Ball();
Brick brick = new Brick(Pong.WIDTH, Pong.HEIGHT / 3);
JLabel label, gameOverLabel;
Timer time;
public GamePanel() {
super();
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
time = new Timer(50, this);
time.start();
this.addKeyListener(this);
setFocusable(true);
// Displaying score
label = new JLabel();
gameOverLabel = new JLabel();
gameOverLabel.setPreferredSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
gameOverLabel.setAlignmentX(CENTER_ALIGNMENT);
label.setAlignmentX(CENTER_ALIGNMENT);
add(label);
add(gameOverLabel);
}
private void update() {
player.update();
if (ball.update()) {
gameOverLabel.setText("GAME OVER");
time.stop();
}
ball.checkCollisionWith(player);
ball.checkBrickCollision(brick);
}
public void paintComponent(Graphics g) {
g.setColor(Color.LIGHT_GRAY);
g.fillRect(0, 0, getWidth(), getHeight());
player.paint(g);
ball.paint(g);
brick.paint(g);
}
public void actionPerformed(ActionEvent e) {
update();
label.setText("Score: " + ball.getScore());
repaint();
}
#Override
public void keyPressed(KeyEvent e) {
// Speed of player
int playerVelocity = 8;
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
player.setXVelocity(playerVelocity);
} else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
player.setXVelocity(-playerVelocity);
} else if (e.getKeyCode() == KeyEvent.VK_R) {
ball = new Ball();
player = new Player();
ball.setScore(0);
label.setText("Score: " + ball.getScore());
gameOverLabel.setText("");
repaint();
time.start();
}
}
#Override
public void keyReleased(KeyEvent e) {
player.setXVelocity(0);
}
#Override
public void keyTyped(KeyEvent e) {
}
}
please help! thank you...
public void paint(Graphics g){
for(Rectangle rect : arr){
g.setColor(new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256)));
g.fillRect(rect.x, rect.y, rect.width, rect.height);
}
}
Indeed it change color on every repaint - you're creating new random Color on every call. I think you should create color in Brick constructor and reuse it.