Reputation: 50
I have a program that displays a picture of a coin. When the user clicks the coin the coin changes from heads to tails and vice versa. That works fine. The problem arises when I want to have a button that flips the coin a random number of times (In this case between 3 and 10 times inclusive). The method used to change the image icon:
flip.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e1) {
playerCoinState = coinState;
System.out.println("Clicked");
int flips = (new Random().nextInt(8)) + 3;
for(int i = 0; i < flips; i++){
try{
Thread.sleep(1000);
}catch(InterruptedException e2){
System.exit(1);
}
System.out.println("Auto Flipped");
changeFace();
}
}
});
And this is the method used to change the ImageIcon of the JLabel coin:
private void changeFace(){
System.out.println("Changing...");
switch(coinState){
case 0:
System.out.println("Coin State 0");
try {
coin.setIcon(new ImageIcon(ImageIO.read(new File("res/Heads.png"))));
} catch (IOException e) {
e.printStackTrace();
}
coinState = 1;
break;
case 1:
System.out.println("Coin State 1");
try {
coin.setIcon(new ImageIcon(ImageIO.read(new File("res/Tails.png"))));
} catch (IOException e) {
e.printStackTrace();
}
coinState = 0;
break;
}
}
The JLabel coin is initialised as:
coin = new JLabel(new ImageIcon("res/Tails.png"));
coinState represents the value of the coin. 0 for heads, 1 for tails. playerCoinState is used to keep track of the coin state the player has selected before the coin is to be flipped by the computer the random amount of times.
Upvotes: 1
Views: 1064
Reputation: 50
MadProgrammer helped me to solve this.
The new and improved ActionListener for the button is:
flip.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e1) {
playerCoinState = coinState;
int flips = (new Random().nextInt(10) + 5);
Timer timer = new Timer(400, new ActionListener(){
int counter = 0;
@Override
public void actionPerformed(ActionEvent e) {
if(counter == flips){
((Timer)e.getSource()).stop();
}
changeFace();
counter++;
}
});
timer.start();
}
});
Thanks again MadProgrammer =)
Upvotes: 0
Reputation: 347334
This...
for(int i = 0; i < flips; i++){
try{
Thread.sleep(1000);
}catch(InterruptedException e2){
System.exit(1);
}
System.out.println("Auto Flipped");
changeFace();
}
Is blocking the event dispatching thread, preventing ui from been updated until after the method exits
You should try using a Swing Timer
instead, which acts as a pseudo loop, but waits in the background for a prescribed period of time before triggering a tick within the context of the EDT, making it safe to update the UI from
Upvotes: 1
Reputation: 29
coin = new JLabel(new ImageIcon((ImageIO.read(new File("path"))));
Use this instead of coin.setIcon(new ImageIcon(ImageIO.read(new File("res/Tails.png"))));
So you are creating the coin label new every time. If you are working with eclispe and windowbuilder, you can just use the tools on the sidebar.
Upvotes: 1