Change the background of a panel multiple times in the same method - java

Hi i'm trying to change the background of a panel to create something similar to the Simon color games.
Here's what I have for code. The problem I seem to be finding is that the only time the background physically changes only at the end of the button being pressed. I have tried using Repaint(); and it has had no effect.
private void ClickRandomColorActionPerformed(java.awt.event.ActionEvent evt) {
Random gen = new Random();
for(int i = 0; i < 5; i++){
int CaseNum = 0;
CaseNum = gen.nextInt(3) +1;
ChangeBackground(CaseNum);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException ex) {
Logger.getLogger(Testerino.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public void ChangeBackground(int i){
System.out.println(i);
if(i == 1){
RandColor.setBackground(blue);
}
else if (i == 2){
RandColor.setBackground(black);
}
else if(i == 3){
RandColor.setBackground(magenta);
}
}

Related

JPanel doesn't get new values (anymore)

So, I'm trying to program a Game of Life simulation (Conway), and I want to show it in a JFrame.
For this purpose, I've created a JPanel, and it works perfectly, until I try to actually show a new generation. With prints, I've figured out, that the list is actually correct inside the newGeneration() method, but when paint(Graphics g) gets called (aka, when I try to repaint the JFrame), the list isn't updating.
I'm sure I've missed something obvious, and I'm not well versed in Java, but it's just getting so annoying. I'd really appreciate your help.
Here's my code;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Main {
public static void main(String[] args) {
new GameOfLife();
}
}
class GameOfLife {
// Initialising all class wide variables; sorted by type
JFrame frame = new JFrame("Game of Life");
JPanel panel;
Scanner gameSize = new Scanner(System.in);
String dimensions;
String splitHorizontal;
String splitVertical;
String confirmation;
Boolean accepted = false;
Integer split;
Integer horizontal;
Integer vertical;
Integer livingNeighbours;
int[][] cells;
int[][] newCells;
public GameOfLife() {
// Prompt for game Size
System.out.println("Please enter your game size in the following format; 'Horizontal,Vertical'");
// Run until viable game Size has been chosen
while (!accepted) {
dimensions = gameSize.nextLine();
// Check for correct format
if (dimensions.contains(",")) {
split = dimensions.indexOf(",");
splitHorizontal = dimensions.substring(0, split);
splitVertical = dimensions.substring(split + 1);
// Check for validity of inputs
if (splitHorizontal.matches("[0-9]+") && splitVertical.matches("[0-9]+")) {
horizontal = Integer.parseInt(dimensions.substring(0, split));
vertical = Integer.parseInt(dimensions.substring(split + 1));
// Check for game Size
if (horizontal > 1000 || vertical > 1000) {
System.out.println("A game of this Size may take too long to load.");
} else {
// Confirmation Prompt
System.out.println("Your game will contain " + horizontal + " columns, and " + vertical + " rows, please confirm (Y/N)");
confirmation = gameSize.nextLine();
// Check for confirmation, anything invalid is ignored
if (confirmation.matches("Y")) {
accepted = true;
System.out.println("Thank you for your confirmation. Please select live cells. Once your happy with your game, press Spacebar to start the Simulation.");
// Setting parameters depending on Size
frame.setSize(horizontal * 25 + 17, vertical * 25 + 40);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
}
}
// Prompt asking for new dimensions in case of invalid dimensions or non confirmation
if (!accepted) {
System.out.println("Please enter different dimensions.");
}
}
// Creating list of cells
cells = new int[horizontal][vertical];
// Showing the empty panel for selection of live cells
panel = new PaintCells(horizontal, vertical, cells);
frame.add(panel);
// Select live cells
panel.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
if (cells[(int) Math.ceil(e.getX() / 25)][(int) Math.ceil(e.getY() / 25)] == 1) {
cells[(int) Math.ceil(e.getX() / 25)][(int) Math.ceil(e.getY() / 25)] = 0;
} else {
cells[(int) Math.ceil(e.getX() / 25)][(int) Math.ceil(e.getY() / 25)] = 1;
}
frame.repaint();
}
});
// Simulation start
frame.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
if (e.getKeyChar() == ' ') {
newGeneration();
}
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
});
}
// Generating new generations
void newGeneration() {
newCells = new int[horizontal][vertical];
// Pause inbetween generations
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
/*
* Way of Life Rules:
* Living cells with 2 or 3 living neighbours live on to the next generation.
* Dead cells with exactly 3 living neighbours become living cells in the next generation.
* Every other living cell dies.
*/
// iterate through every cell
for (int l = 0; l < vertical; l++) {
for (int k = 0; k < horizontal; k++) {
livingNeighbours = 0;
// check amount of neighbours
if (k - 1 > -1) {
if (l - 1 > -1) {
if (cells[k - 1][l - 1] == 1) {
livingNeighbours++;
}
}
if (l + 1 < vertical) {
if (cells[k - 1][l + 1] == 1) {
livingNeighbours++;
}
}
if (cells[k - 1][l] == 1) {
livingNeighbours++;
}
}
if (k + 1 < horizontal) {
if (l - 1 >= 0) {
if (cells[k + 1][l - 1] == 1) {
livingNeighbours++;
}
}
if (l + 1 < vertical) {
if (cells[k + 1][l + 1] == 1) {
livingNeighbours++;
}
}
if (cells[k + 1][l] == 1) {
livingNeighbours++;
}
}
if (l - 1 >= 0) {
if (cells[k][l - 1] == 1) {
livingNeighbours++;
}
}
if (l + 1 < vertical) {
if (cells[k][l + 1] == 1) {
livingNeighbours++;
}
}
// change cell value depending on amount of neighbours
if (cells[k][l] == 1) {
if (livingNeighbours < 2 || livingNeighbours > 3) {
newCells[k][l] = 0;
} else {
newCells[k][l] = 1;
}
} else {
if (livingNeighbours == 3) {
newCells[k][l] = 1;
}
}
}
}
cells = newCells;
frame.validate();
frame.paint(frame.getGraphics());
newGeneration();
}
}
// Our canvas
class PaintCells extends JPanel {
private Integer horizontal;
private Integer vertical;
private int[][] newOriginalCells;
// Get our X and Y from the original prompts
public PaintCells(Integer originalHorizontal, Integer originalVertical, int[][] originalCells) {
this.horizontal = originalHorizontal;
this.vertical = originalVertical;
this.newOriginalCells = originalCells;
}
#Override
public void paint(Graphics g) {
for (int i = 0; i < vertical; i++) {
for (int j = 0; j < horizontal; j++) {
// Check cell value
if (newOriginalCells[j][i] == 1) {
g.setColor(Color.black);
} else {
g.setColor(Color.white);
}
// paint according to value
g.fillRect(j * 25, i * 25, 25, 25);
if (newOriginalCells[j][i] == 1) {
g.setColor(Color.white);
} else {
g.setColor(Color.black);
} // maybe change style?
g.drawRect(j * 25, i * 25, 25, 25);
}
}
}
}
I'm guessing, the problem is somewhere in newGeneration(), but other than that, I really have no idea anymore.
You have a common problem which I had myself a few months ago.
Java Swing GUI system works in thread called Event Dispatch Thread (EDT). This thread handle events like mouse clicks, typing etc. and paint the components to the screen. You should use this thread not as your main thread, but as sub-thread which working only once a certain time/when event happens, and not let him run continuously. In your code, since the user choose the cell to live, this thread run non-stop (because you started the program inside a listener, which is part of the EDT), and your GUI stuck, because it's updating only at the end of the thread.
You can solve this by using javax.swing.Timer. Timer is an object that allows you do tasks once a while, and it is perfect to this problem.
Use code like this:
ActionListener actionListaner = new ActionListener(){
public void actionPerformed(ActionEvent e){
//Put here you ne genration repeating code
}
};
int delay = 1000;//You delay between generations in millis
Timer timer = new timer(delay, actionListener);
The code in the actionPerformed method will repeat every second (or any other time you want it to repeat), and every operation of the timer will recall EDT instead of let it run non-stop.

I'm trying to delete an object in my world that is saved in an ArrayList but it doesn't work

I use dyn4j physics engine (although I don't think it's relevant for my question).
I don't get any errors but if I press the right mouse button on one of the objects it doesn't delete the object.
Does anyone know what might be the problem?
Here I add the objects to my world:
public void mouseClicked(MouseEvent e) {
double x = e.getPoint().getX()/100;
double y = e.getPoint().getY()/100;
if (addBlocks.isSelected()) {
BodyFixture fblock = new BodyFixture(Geometry.createRectangle(1,1));
dblock = new Body();
if (e.getButton() == MouseEvent.BUTTON1) {
dblock.addFixture(fblock);
dblock.getTransform().setTranslation(x,y);
dblock.setMass(MassType.NORMAL);
dblock.getFixture(0).setRestitution(0.3);
world.addBody(dblock);
gameObjects.add(new GameObject("dirtblock.png", dblock, new Vector2(0, 0), 0.8));
}
}
}
And here I'm trying to delete them:
if (e.getButton() == MouseEvent.BUTTON3) {
for (int i = 0; i < gameObjects.size(); i++) {
if (gameObjects.get(i).contains(e.getPoint())) {
world.removeBody(gameObjects.get(i).body);
gameObjects.remove(i);
}
}
}
Usually when you are deleting items with index in a loop you start the loop at the end of the collection due to indices changing i.e. try this:
if (e.getButton() == MouseEvent.BUTTON3) {
for (int i = gameObjects.size() - 1; i >= 0 ; i--) {
if (gameObjects.get(i).contains(e.getPoint())) {
world.removeBody(gameObjects.get(i).body);
gameObjects.remove(i);
}
}
}

How do I remove the line of TextArea where caret is located

what I tried to do is if when I call the function then the line disappeared where caret is located in JTextArea. I achieved at first line case but hard to do in middle and last line cases.
This is perfectly failed code what I did.
private void DeleteOptionActionPerformed(ActionEvent e) {
String[] lines = area.getText().split("\n");
int caret = area.getCaretPosition();
int beforeLocation = 0;
for(int i = 0; i < area.getLineCount(); i++) {
try {
if(i == 0) {
if(caret <= lines[i].length())
area.replaceRange(null, area.getLineStartOffset(i), area.getLineEndOffset(i));
}
else {
if(caret <= lines[i].length() && caret > lines[beforeLocation].length()) {
area.replaceRange(null, area.getLineStartOffset(i), area.getLineEndOffset(i));
}
else {
caret -= lines[i].length();
beforeLocation = i;
continue;
}
}
} catch(BadLocationException e1) {
e1.printStackTrace();
}
caret -= lines[i].length();
beforeLocation = i;
}
}
Try using the Utilities class.
No need for any looping logic. Code should be something like:
int offset = textArea.getCaretPosition();
int start = Utilities.getRowStart(...);
int end = Utilities.getRowEnd(...);
textArea.replaceRange("", start, end);

Memory game does not call compare function correctly

I have coded a simple memory game. Card values are added to two arrays and after that, a compare function is called. But there is a problem with the logic of the compare function.
The specific problem seems related to the fact that the compare function is called on the third button click. So on first click it adds first value to first array , on second click second value to second array. But I must click for yet a third time to call the compare function to compare the match of two arrays.
The main problem is that after all cards are inverted (10 matches in 5x4 memory game), it does not show the result.
I have uploaded full code here : http://uloz.to/xcsJkYUK/memory-game-rar .
public class PEXESO5x4 extends JFrame implements ActionListener {
private JButton[] aHracieTlactika = new JButton[20];
private ArrayList<Integer> aHodnoty = new ArrayList<Integer>();
private int aPocitadlo = 1;
private int[] aTlacitkoIden = new int[2];
private int[] aHodnotaTlac = new int[2];
private JButton aTlacitkoExit;
private JButton aTlacitkoReplay;
private JButton[] aHracieTlacitko = new JButton[20];
private int aPocetTahov = 0;
public void vkladanieHodnot() {
for (int i = 0; i < 2; i++) {
for (int j = 1; j < (this.aHracieTlactika.length / 2) + 1; j++) {
this.aHodnoty.add(j);
}
}
Collections.shuffle(this.aHodnoty);
}
public boolean zhoda() {
if (this.aHodnotaTlac[0] == this.aHodnotaTlac[1]) {
return true;
}
return false;
}
public void zapisCislaDoSuboru() {
try(PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("Semestralka.txt", true)))) {
out.println("haha");
//more code
out.println("hahahahha");
//more code
}catch (IOException e) {
//exception handling left as an exercise for the reader
}
}
public void actionPerformed(ActionEvent e) {
int match = 0;
if (this.aTlacitkoExit == e.getSource()) {
System.exit(0);
}
if (this.aTlacitkoReplay == e.getSource()) {
}
for (int i = 0; i < this.aHracieTlactika.length; i++) {
if (this.aHracieTlactika[i] == e.getSource()) {
this.aHracieTlactika[i].setText("" + this.aHodnoty.get(i));
this.aHracieTlactika[i].setEnabled(false);
this.aPocitadlo++;
this.aPocetTahov += 1;
if (this.aPocitadlo == 3) {
if (this.zhoda()) {
match+=1;
if (match==10)
{
System.out.println("You win");
}
this.aHracieTlactika[this.aTlacitkoIden[0]].setEnabled(false);
this.aHracieTlactika[this.aTlacitkoIden[1]].setEnabled(false);
} else {
this.aHracieTlactika[this.aTlacitkoIden[0]].setEnabled(true);
this.aHracieTlactika[this.aTlacitkoIden[0]].setText("");
this.aHracieTlactika[this.aTlacitkoIden[1]].setEnabled(true);
this.aHracieTlactika[this.aTlacitkoIden[1]].setText("");
}
this.aPocitadlo = 1;
}
if (this.aPocitadlo == 1) {
this.aTlacitkoIden[0] = i;
this.aHodnotaTlac[0] = this.aHodnoty.get(i);
}
if (this.aPocitadlo == 2) {
this.aTlacitkoIden[1] = i;
this.aHodnotaTlac[1] = this.aHodnoty.get(i);
}
}
}
}
}

What to put in my if statement

Ok so I have created a game and it works perfectly, except I don't want the player to win after just one defeat I want him to have to kill 10 enemies well I created my spawnmore method and I know the problem I just don't know how to fix it, in my if statement I have it saying if(dead < 10) then do my stuff, when I only want it to do it once every time dead increments one if you get what I mean here's my method thanks
public void spawnMore(){
int delay = 1000;
Timer time = new Timer(delay, new ActionListener(){
public void actionPerformed(ActionEvent e){
if(WizardCells[BadGuy.getx()][BadGuy.gety()].getIcon() != null){
return;
}
if(WizardCells[BadGuy.getx()][BadGuy.gety()].getIcon() == null){
dead += 1;
}
if(dead < 10){
int where = (int)(10 + Math.random() *9);
BadGuy.spawnEnemy(where, where);
move();
}
}
});
time.start();
}
If I understand you correctly, you could just move the if statement inside the previous if statement:
public void spawnMore(){
int delay = 1000;
Timer time = new Timer(delay, new ActionListener(){
public void actionPerformed(ActionEvent e){
if(WizardCells[BadGuy.getx()][BadGuy.gety()].getIcon() != null){
return;
}
if(WizardCells[BadGuy.getx()][BadGuy.gety()].getIcon() == null){
dead += 1;
if(dead < 10){
int where = (int)(10 + Math.random() *9);
BadGuy.spawnEnemy(where, where);
move();
}
}
}
});
time.start();
}

Categories