Java Swing and Thread sleeping - java

I decided to make something fun as a break from reading programming books, and I have hit a snag. This is my first swing program, and am ready to wrap it up!
The problem: I clearly don't understand how threads work with Swing. I am writing a GUI for a black jack game, and I did all of the functionality first e.g. drawing a new card to the screen when the player hits, showing the dealer hit after the player decides to stay, etc. This all works.
When I added in the logic to check for a user bust when hitting, or who wins when the user decides to stay, the game instantly goes to the win/loss screen before drawing either: the card the user got that caused a bust, or; the cards that the dealer drew when hitting (if any).
I tried inserting Thread.sleep in various places, to no avail. The program would sleep before drawing the card, then end instantly as above (even though it was placed logically after the call to draw, and before the call to calculate a winner).
also I tried to follow the MVC paradigm here, just fyi.
P.S. my program runs on one thread, I do not explicitly instantiate another, but I vaguely remember reading that Swing spawns it's own thread for graphics stuff
Sorry for that long intro! Here is some code:
The Model class' pertinent methods
void hit() {
//run when button is clicked
player.hand.add(deck.deck.get(0));
deck.deck.remove(0);
}
boolean isBust() {
if (player.getScore() > 21)
return true;
return false;
}
void dealerHit() {
while (dealer.getScore() < 17) { //could implement soft 17 rules for more difficulty
dealer.hand.add(deck.deck.get(0));
setChanged();
notifyObservers();
deck.deck.remove(0);
//Here was one attempt
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
boolean isWin() {
//and another
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
if ((player.getScore() > dealer.getScore() && player.getScore() <= 21) || dealer.getScore() > 21)
return true;
return false;
}
void stay() {
dealerHit();
isWin();
}
View Class
void addHitListener(ActionListener HitListener) {
hit.addActionListener(HitListener);
}
void addStartListener(ActionListener StartListener) {
start.addActionListener(StartListener);
}
void addStayListener(ActionListener StayListener) {
stay.addActionListener(StayListener);
}
void display() {
JFrame myFrame = new JFrame("BlackJack");
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.setContentPane(this);
myFrame.setPreferredSize(new Dimension(700,550));
myFrame.pack();
myFrame.setVisible(true);
}
void addCards(Player p, Dealer d) {
topPanel.remove(start);
pcardPanel.add(playerlabel);
dcardPanel.add(dealerlabel);
for (Card c : p.hand) {
ImageIcon cc = new ImageIcon(c.img);
JLabel cC = new JLabel(cc);
//cC.setAlignmentX(alignmentX); use to get X alignment of card 1 & 2 for splits
//cC.setAlignmentY(alignmentY); same for Y, then increment by .3f
pcardPanel.add(cC);
}
for (Card c : d.hand)
dcardPanel.add(new JLabel(new ImageIcon(c.img)));
topPanel.add(new JLabel("Options: "));
topPanel.add(hit);
topPanel.add(stay);
validate();
repaint();
}
void endGame(boolean isWin) {
//I think I tried here, too
removeAll();
setBackground(new Color(0, 122, 0));
if (isWin == true)
add(new JLabel("You won!"));
else
add(new JLabel("You Lost"));
validate();
repaint();
}
public void hitPlayer(Player p) {
JLabel hits = new JLabel(new ImageIcon(p.hand.get(p.hand.size()-1).img));
//hits.setAlignmentY(alignmentY);
pcardPanel.add(hits);
validate();
repaint();
}
public void hitDealer(Dealer d) {
dcardPanel.add(new JLabel(new ImageIcon(d.hand.get(d.hand.size()-1).img)));
validate();
repaint();
}
Controller class:
public class Controller implements Observer {
BlackJack game;
Table t;
Controller(BlackJack game, Table t) {
this.game = game;
this.t = t;
this.game.addObserver(this);
this.t.addHitListener(new HitListener());
this.t.addStartListener(new StartListener());
this.t.addStayListener(new StayListener());
}
public void go() {
t.display();
}
public void update(Observable obj, Object observed) {
t.hitDealer(game.getDealer());
}
class HitListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
game.hit();
t.hitPlayer(game.getPlayer());
if (game.isBust() == true)
t.endGame(false);
}
}
class StartListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
t.addCards(game.getPlayer(), game.getDealer());
}
}
class StayListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
game.stay();
//doStay();
if (game.isWin() == true)
t.endGame(true);
else
t.endGame(false);
}
}
I just had a thought, since I'm doing this in the actionPerformed methods, could that be why sleep seemed to affect the GUI thread, and not draw the card(s) then sleep. I bet that is it. But I'm going to eat dinner, hopefully someone smarter than myself can lend a hand! Thanks in advance
P.P.S. if there are any typos (I don't think there are) just know that it all compiles and works! And no warnings, if that helps

Swing is indeed a single-thread library, like most UIs. There are also many optimizations to make it work fast. Case in point - most paintings are cached and displayed together. Even if this was not the case, you'd be relying on the speed of the system, which is not a good idea.
If you want a delayed action, you need to use swing's timer (not to be confused with the other timer class). That class has an action listener that goes off when the timer expires. In your case, you'd detect the win/bust condition, start the timer (e.g to fire in 2 seconds) and continue the drawing as usual.

This is a little too long for me to read and understand... But I guess your problem is because you are processing everything in the Event Dispatching Thread.
When you paint something on the GUI and then have more processing, the paint will actually reflect on the GUI only when the whole of the thread has finished processing. That's why you are not seeing your drawing before your Thread.sleep method.
Instead you should use SwingWorker to split your processing and GUI updating to different threads.
Look at this https://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html

Related

Why is my Java game crashing when I add a game loop?

I've recently started to try to learn java. I thought maybe making small games would be the best way to get familiar with java, so that's what I'm doing. So, I started my first game, and it's looking good. It's just a grid with a player in the center. Once I tried adding player movement I realized I'd need a game loop to check for key presses. That's what I tried. All I can say is that I've never made a game loop before, so this is what I attempted:
public static void main(String[] args) {
GamePanel panel = new GamePanel();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createGui();
double ns = 1000000000.0 / 60.0;
double delta = 0;
long lastTime = System.nanoTime();
long timer = System.currentTimeMillis();
while (true) {
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while (delta >= 1) {
panel.checkKeys();
delta--;
}
}
}
});
}
Here's the issue... When I run this, my game just crashes. It doesn't even let me close out of the game. What is going on? Just in case, I will show more of the GamePanel code (please tell me if you need any more code).
public GamePanel() {
setLayout(new GridLayout(tiles_count, tiles_count));
setBackground(Color.gray);
setFocusable(true);
addKeyListener(this);
tile_size = 40;
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_A) {
System.out.println("A PRESSED");
player.x += 40;
left = true;
}
}
#Override
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_A) {
System.out.println("A RELEASED");
left = false;
}
}
#Override
public void keyTyped(KeyEvent e) {
}
public void checkKeys() {
if(left) {
System.out.println("LEFT");
} else {
System.out.println("!LEFT");
}
}
The game structure is like this: I have a Main class, which runs a GamePanel class as the main(String args) {} function. This issue might have to be with the fact that im using the run method in the Main class instead of the GamePanel class.
What am I doing wrong? Any help is very much appreciated!
Your while loop will never exit, and thus your program can never repaint, etc.
However, for a game loop like this, you do want an infinite loop --- you just want to run it in a different thread. In this way, the rest of your program is not blocked by the infinite loop, however you are still able to run your game loop tasks.
To do this, we make a new thread, and run our loop in there instead. Note also that after each loop we sleep for a little while (ideally you'd want to do this with time deltas, etc, this is just an example) --- this means that we cap the amount of frames per second, meaning that we don't overwork the processor for no good reason.
Thread t = new Thread(new Runnable(){
public void run() {
while (true) {
// your update logic here
try {
Thread.sleep(16);
}
catch(InterruptedException) {}
}
}
});
t.start();
I believe the issue is that you have an infinite loop. This occurs when the condition for your loop will always remain true. while(True). You either need to implement a break; statement which will terminate the loop or use a condition in your while loop that will run the loop until a certain condition is met while(some-condition == true). Hopefully, this helps.
https://codesnippets.fandom.com/wiki/Infinite_Loop

I'm probably doing this incorrectly. Is there a better way?

So usually when I make mock-up programs (like this one) I look for things I can improve on in case the situation happens again.
Today I thought I'd brush up on basic OOP (I understand the concept of OOP, just haven't messed around with it for a bit and wanted to freshen my memory). So I decided to make a little game that just creates 3 monsters on a 10x10 plane and 1 player (you), you are able to move your player in any x/y direction. My program works but I can't help but feel that I'm doing something incorrectly.
So the basic layout of my program was to have 5 classes. A GUI class that shows the game and gives you directional buttons for movement control, a class that creates the monsters, a class that creates the players, a class that creates the 10x10 board and keeps track of monster/player locations, and of course a main class that creates all the objects and has the main game loop and whatnot.
I was having a bit of a hard time interacting with my main class and my GUI class. What I ended up doing was doing a while loop in my main class and waiting until the player presses the start button, and once the player presses it (via action listener) the GUI class sets a public variable (running) from false to true, and I am able to act accordingly once the variable is changed.
HERE is where I feel like I am doing something wrong: At first my while loop would not terminate unless I printed out to the console. I Googled the issue and apparently people have said that it's some sort of issue with threading or "active polling", which I did not understand. I went to my program and added a small 10ms thread sleep in my while loops and everything started working great.
My question to you guys is, what is active polling? Why is it bad? How/why/where was this going on in my program? And finally if there's a better way of interacting with a GUI class and a main class. Sorry for the giant wall of text but I like to be thorough when explaining a situation!
TL;DR: Am I interacting correctly with my GUI class and my main class? If not what is the proper way to do it?
My main class:
public class MainGame {
public static void main(String[] args) throws InterruptedException{
ShowGUI gui = new ShowGUI();
while(!gui.running){
Thread.sleep(10);
}
Board gameBoard = new Board();
gui.setLabelText(gameBoard.getBoard());
//Add Player
Player playerOne = new Player(1000, "Player 1");
//Add monsters
Monster monstMatt = new Monster(1000, "Matt");
Monster monstJon = new Monster(1000, "Jon");
Monster monstAbaad = new Monster(1000, "Abaad");
while(gui.running){
Thread.sleep(10);
int x, y;
x = playerOne.getX();
y = playerOne.getY();
if(gui.buttonPress != -1){
if(gui.buttonPress == 1){
playerOne.move(x, --y);
}else if(gui.buttonPress == 2){
playerOne.move(x, ++y);
}else if(gui.buttonPress == 3){
playerOne.move(--x, y);
}else if(gui.buttonPress == 4){
playerOne.move(++x, y);
}
gui.buttonPress = -1;
gui.setLabelText(gameBoard.getBoard());
}
}
}
}
My GUI Class:
public class ShowGUI{
private JTextArea board;
private JButton moveUp;
private JButton moveDown;
private JButton moveLeft;
private JButton moveRight;
public boolean running = false;
public int buttonPress = -1;
public ShowGUI(){
System.out.println("GUI Successfully Loaded");
createAndShow();
}
private void createAndShow(){
JFrame mainFrame = new JFrame("Bad Game");
addComponents(mainFrame.getContentPane());
mainFrame.setSize(500, 400);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setLocationRelativeTo(null);
mainFrame.setResizable(false);
mainFrame.setVisible(true);
}
private void addComponents(Container pane){
pane.setLayout(null);
board = new JTextArea(1, JLabel.CENTER);
moveUp = new JButton("Up");
moveDown = new JButton("Down");
moveLeft = new JButton("Left");
moveRight = new JButton("Right");
moveUp.setBounds(185, 225, 130, 35);
moveLeft.setBounds(115, 280, 130, 35);
moveRight.setBounds(255, 280, 130, 35);
moveDown.setBounds(185, 335, 130, 35);
board.setEditable(false);
board.setBounds(115, 30, 270, 145);
board.setFont(new Font("Consolas", Font.BOLD, 12));
addActionListeners();
pane.add(board);
pane.add(moveUp);
pane.add(moveRight);
pane.add(moveLeft);
pane.add(moveDown);
}
private void addActionListeners(){
moveUp.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
running = true;
buttonPress = 1;
}
});
moveDown.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
buttonPress = 2;
}
});
moveLeft.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
buttonPress = 3;
}
});
moveRight.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
buttonPress = 4;
}
});
}
public void setLabelText(char[][] boardToShow){
board.setText(" ");
for(int i = 0; i < boardToShow.length; i++){
for(int j = 0; j < boardToShow[i].length; j++){
board.append(boardToShow[i][j] + " ");
}
board.append("\n ");
}
}
}
If you require my Board/Monster/Player classes I can post them, but I don't think the problem is with those classes.
Active polling (a.k.a. busy waiting) is when a program checks over and over whether some condition is true, and since we're talking about computers, this is usually done many times a second. It's bad because it means the process is constantly using up CPU to check for this condition, and, even worse, because it uses up so much of the CPU, it can prevent the condition from being able to become true in the first place (this is what is happening in your case).
I'll try to explain this with a metaphor, where your Main class (specifically your while(gui.running) loop) is the boss, and the GUI class is the employee. Imagine the boss comes to his employee every second and asks "Have you done what I asked you to do?". By doing so every second, not only is the boss wasting his time, but is actually preventing his employee from being able to do what he was asked to do.
That is exactly what is happening between your Main and GUI class. The value of buttonPress can not change when the while loop keeps running, and that's why sleeping (and printing to console, because that requires an IO operation which also blocks the thread for a while) makes it work, because the while loop stops executing for a short amount of time, giving your program the chance to change the value of buttonPress.
The solution
In order to solve this, let's go back to the boss/employee metaphor. Instead of checking every second, the boss should say, "When you are done doing this, come and tell me". That way he doesn't need to keep checking on the employee and the employee has time to do the task. Similarly, your GUI class should call a method in your Main class when the actionListeners are fired. Ultimately, as other people pointed out, your structure needs quite a bit of work and clean up, I would recommend you look into using the Model-View-Controller pattern.
However I will propose a solution which will work for the setup you currently have. Your Main class should look something like:
public class Main {
private Player playerOne;
private Monster monstMatt;
private Monster monstJon;
private Monster monstAbaad;
private ShowGUI gui;
private Board gameBoard;
public Main() {
//Add Player
playerOne = new Player(1000, "Player 1");
//Add monsters
monstMatt = new Monster(1000, "Matt");
monstJon = new Monster(1000, "Jon");
monstAbaad = new Monster(1000, "Abaad");
gui = new ShowGUI(this);
gameBoard = new Board();
gui.setLabelText(gameBoard.getBoard());
}
public movePlayerUp() {
movePlayer(0, -1);
}
public movePlayerDown() {
movePlayer(0, 1);
}
public movePlayerLeft() {
movePlayer(-1, 0);
}
public movePlayerRight() {
movePlayer(1, 0);
}
private movePlayer(x, y) {
playerOne.move(playerOne.getX() + x, playerOne.getY() + y);
}
}
And the GUI class:
public class ShowGUI {
private Main main;
public ShowGui(Main main) {
this.main = main;
createAndShow();
System.out.println("GUI Successfully Loaded");
}
private void addActionListeners(){
moveUp.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
main.movePlayerUp();
}
});
moveDown.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
main.movePlayerDown();
}
});
moveLeft.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
main.movePlayerLeft();
}
});
moveRight.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
main.movePlayerRight();
}
});
}
/* All the other methods you have */
...
}
So instead of using flags (buttonPress=2), use methods which will be called when a certain action occurs. Again, this is not a perfect long-term solution, but it has the right gist and is the sort of pattern you should follow.

Rectangle colouring logic

I have one three rectangles in my canvas. I wanted to change the colours of three rectangles
in a slow manner one by one.
For example: When starting the application, user should be able to see three rectangles with the same colour (blue).
After 2 secons that rectangles colour should change to red.
Again after 2 secons the next rectangles colour should get changed.
The last one is also done the same way, that means after 2 seconds of the 2nd rectangle.
I wrote in my own way. But it is not working. All the rectanlges are changed together. I want one by one.
Could anyone give me the logic.
final Runnable timer = new Runnable() {
public void run() {
//list of rectangles size =3; each contain Rectangle.
for(int i = 0 ; i < rectangleList.size();i++){
if(rectangleListt.get(i).getBackgroundColor().equals(ColorConstants.blue)){
try {
rectangleList.get(i).setBackgroundColor(ColorConstants.yellow);
Thread.sleep(1500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//rectSubFigureList.get(i).setBorder(null);
}/*else{
rectSubFigureList.get(i).setBackgroundColor(ColorConstants.blue);
}*/
}
You're likely calling Thread.sleep inside of Swing's event thread or EDT (for event dispatch thread), and this will cause the thread itself to sleep. Since this thread is responsible for all of Swing's graphics and user interactions, this will in effect put your entire application to sleep, and is not what you want to have happen. Instead, read up on and use a Swing Timer for this.
References:
Swing Timer tutorial
Swing Event Dispatch Thread and Swingworker tutorial
To expand on Hidde's code, you could do:
// the timer:
Timer t = new Timer(2000, new ActionListener() {
private int changed = 0; // better to keep this private and in the class
#Override
public void actionPerformed(ActionEvent e) {
if (changed < rectangleList.size()) {
rectangleList.setBackgroundColor(someColor);
} else {
((Timer) e.getSource()).stop();
}
changed++;
}
});
t.start();
You can set a Timer:
// declaration:
static int changed = 0;
// the timer:
Timer t = new Timer(2000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Change the colour here:
if (changed == 0) {
// change the first one
} else if (changed == 1) {
// change the second one
} else if (changed == 2) {
// change the last one
} else {
((Timer) e.getSource()).stop();
}
changed ++;
}
});
t.start();

Trigger event only after repaint in Java Swing?

I am making a simple board game in java, where I want to animate a dice roll. So I flash pictures of a dice like this:
public Timer roll_dice = new Timer(50, this);
...
public void actionPerformed(ActionEvent evt) {
if(roll_dice.getDelay() > 500){
roll_dice.setDelay(50);
roll_dice.stop();
movePiece();
}else{
roll_dice.setDelay(roll_dice.getDelay() + 50);
dice_panel.repaint(0);
}
}
}
movePiece(){
//do some more painting
}
So the die is going so show random numbers for a few times, and then slowly settle on a number. After that is done I would like to call the movePiece() method. However, as it is, the the repaint occurs sporadically and screws everything up so that movePiece() gets called before the dice roll is actually finished animating.
Does anyone have any ideas how I can call movePiece only after the final repaint has happened?
So the die is going so show random numbers for a few times, and then slowly settle on a number. After that is done I would like to call the movePiece() method. However, as it is, the the repaint occurs sporadically and screws everything up so that movePiece() gets called before the dice roll is actually finished animating.
What worries me here is why your painting is occurring sporadically -- it simply shouldn't be doing that, and perhaps that is what you need to fix. I wonder if you're reading in the images from the file each time you do the drawing or some other cause for slowing the drawing down. If you need more help regarding this issue, then you'll have to give us more information on how you do your painting. Regardless, you should avoid having program logic be dependent on painting as you don't have full control over when or even if painting will occur.
Rather than redrawing images and calling repaint(), why not simply put your rolling dice images into ImageIcons on program start up, and then in your Swing Timer, swap icons in a JLabel? Then stop your Timer when the delay gets long enough and in that if block, move your piece.
So, assuming that you have several dice, each can be displayed by a JLabel that is held in an array of JLabel called diceLabels, and the ImageIcons can be held in an array called diceIcons. Then you can do something like:
public void actionPerformed(ActionEvent e) {
if (roll_dice.getDelay() > 500) {
roll_dice.setDelay(50);
roll_dice.stop();
movePiece(); // I like this -- this shouldn't change
} else {
roll_dice.setDelay(roll_dice.getDelay() + 50);
// dice_panel.repaint(0);
for (JLabel dieLabel : diceLabels) {
int randomIndex = random.nextInt(diceIcons.length);
dieLabel.setIcon(diceIcons[randomIndex]);
}
}
}
I like your logic on when you call movePiece() and I think that this should remain unchanged.
You can call the rolling in another thread and join() the current thread to the rolling one. That way the main code will wait until the roll thread dies (finished rolling).
public void actionPerformed(ActionEvent evt) {
if(roll_dice.getDelay() > 500){
Thread rollerThread = new RollerThread();
rollerThread.start();
rollerThread.join();
movePiece();
}
else{
roll_dice.setDelay(roll_dice.getDelay() + 50);
dice_panel.repaint(0);
}
}
private RollerThread extends Thread
{
public void run(){
roll_dice.setDelay(50);
roll_dice.stop();
}
}
However, this might not work with the EDT - because repaints should be scheduled to the queue. Maybe you can shedule the event using the SwingUtilities.invokeAndWait():
public void actionPerformed(ActionEvent evt) {
Thread thread = new Thread(){
public void run(){
if(roll_dice.getDelay() > 500){
SwingUtilities.invokeAndWait(new Runnable(){
public void run(){
roll_dice.setDelay(50);
roll_dice.stop();
}
});
movePiece();
}
else{
roll_dice.setDelay(roll_dice.getDelay() + 50);
dice_panel.repaint(0);
}
}
};
thread.start();
}
Does anything change if you put that call to movePiece(); in a SwingUtilities.invokeLater(Runnable);?
if(roll_dice.getDelay() > 500){
roll_dice.setDelay(50);
roll_dice.stop();
SwingUtilities.invokeLater(new Runnable() {
public void run() { movePiece(); }
});
}
...

Coloring a JButton in Java

I am struggling with a problem on coloring an array of JButtons.
I made two arrays of JButtons:
public JButton Speler1[] = new JButton[140]; //Player1
public JButton Speler2[] = new JButton[140]; //Player2
These two arrays of buttons make lane 1 and lane 2 of a racing game. I want the position of player 1 and 2 to be colored on both screens. So player 1 can see where player 2 is and vice versa.
I already made a method which sends the position of both players to eachother.
if (message.contains("Positie")) {
String posit = message.replaceFirst("Positie", "");
int positi = Integer.valueOf(posit);
positie2 = positi;
kleurHokje kleur = new kleurHokje();
kleur.hokVerkleur(positi); // positi is the position of each player
}
So when I call the method hokVerkleur(positi), I want to change a button on lane 2.
class kleurHokje{
public void hokVerkleur(int loc){
Speler2[loc].setBackground(Color.yellow);
Speler2[positie2].setBackground(Color.gray);
}
}
It just wont work. While i'm doing almost the same for Speler1[positie] except Speler1 doesn't use the network, which works as I want.
Any help is appreciated,
Thanks Jef
Edit:
If I place my code in one of the MouseListeners it works fine, but rather have it to be colored automatically instead of having to click each time.
class Klaar extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
Speler2[positie2].setBackground(Color.gray);
}
}
Ps. my first language isn't english, I hope you understand my problem.
If I place my code in one of the MouseListeners it works fine:
agreed, if you change Color for JButton from BackGroung Task, then there any changes, you have some issues with Concurency in Swing, your updated to the GUI is out of EDT,
1) then you have to wrap coloring JButtons into invokeLater();
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
Speler2[loc].setBackground(Color.yellow);
Speler2[positie2].setBackground(Color.gray);
}
});
2) but you have to solve by using regular Swing methods
2a) wrap your GUI rellated code to the javax.swing.Action
2b) initialize your BackGroung Tasks from
SwingWorker
Runnble#Tread
Made a runnable thread, works as a charm. Thanks for help everybody.
public void actionThread() {
Thread t = new Thread() {
public void run() {
while (!stop) {
tegenspelerPositie();
Score();
eigenOgen();
try {
sleep(100);
} catch (InterruptedException ex) {
}
}
}
};
t.start();
}

Categories