Problems with my Thread.sleep() - java

I'm creating a simple video poker program and right now I'm working on the action that's performed after the user has specified the cards he wants to hold, and replace the discarded cards with new cards after the draw. I have an Action where I want to replace the cards one by one with a delay between all replacements, but with the code I have below, it'll sleep for 500 ms multiplied by the number of cards I have to replace and THEN replace all the cards at once, rather than replace it one at a time as I want. Any help is greatly appreciated!
Action drawAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
int deckPos = 5;
if((holdValFirst.getText()).equals("HELD")){}
else{
holdFirst.setIcon(new ImageIcon(((deck.getDeck())[deckPos]).getCardName()+".gif"));
deckPos++;
try
{
Thread.sleep(500);
}catch (InterruptedException ie){
System.out.println(ie.getMessage());
}
}
if((holdValSecond.getText()).equals("HELD")){}
else{
holdSecond.setIcon(new ImageIcon(((deck.getDeck())[deckPos]).getCardName()+".gif"));
deckPos++;
try
{
Thread.sleep(500);
}catch (InterruptedException ie){
System.out.println(ie.getMessage());
}
}
if((holdValThird.getText()).equals("HELD")){}
else{
holdThird.setIcon(new ImageIcon(((deck.getDeck())[deckPos]).getCardName()+".gif"));
deckPos++;
try
{
Thread.sleep(500);
}catch (InterruptedException ie){
System.out.println(ie.getMessage());
}
}
if((holdValFourth.getText()).equals("HELD")){}
else{
holdFourth.setIcon(new ImageIcon(((deck.getDeck())[deckPos]).getCardName()+".gif"));
deckPos++;
try
{
Thread.sleep(500);
}catch (InterruptedException ie){
System.out.println(ie.getMessage());
}
}
if((holdValFifth.getText()).equals("HELD")){}
else{
holdFifth.setIcon(new ImageIcon(((deck.getDeck())[deckPos]).getCardName()+".gif"));
deckPos++;
}
}
};

When you sleep inside the event dispatch thread (EDT), the GUI is frozen. Every long running task should be done outside of the EDT, and all swing manipulations should be done in the EDT.
You should use a SwingWorker to sleep in another thread, and publish some progress every 500ms. Or you could use a javax.swing.Timer which would fire an event every 500ms.

Related

How to set JLabel text to display before a system sleep

I'm trying to display the text of Successful Login before a system sleep for 3,000 miliseconds. Its not working when I place it right after the set text. How do I get it to display then pause so there is a bit of delay so the user knows that they loging in?
After the user correctly logs-in it will continue to a different class where the JFrame will close
l_Message.setForeground(Color.green);
l_Message.setText("Succesful Login");
try{
Thread.sleep(3000);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
PLOGIN post_login = new PLOGIN();
post_login.postlogin_UI(login_JFrame);
See Concurrency in Swing for the reason why you're having problems
See How to use Swing Timers for a possible solution
import javax.swing.Timer
//...
l_Message.setForeground(Color.green);
l_Message.setText("Succesful Login");
Timer timer = new Timer(3000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
PLOGIN post_login = new PLOGIN();
post_login.postlogin_UI(login_JFrame);
}
});
timer.start();
Assuming that you are calling this from outside of the GUI thread(which I believe that you should be), you could try the following:
EventQueue.invokeLater(() -> {
l_Message.setForeground(Color.green);
l_Message.setText("Succesful Login");
});
try{
Thread.sleep(3000);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
PLOGIN post_login = new PLOGIN();
post_login.postlogin_UI(login_JFrame);
i.e. schedule GUI operations to the GUI thread

How to fix this code for splash-screen?

I am trying to make splash-screen for a game, both of which are JFrames. I want the splash-screen to open for 3 seconds, then be disposed of. The JFrame for the main part of the game needs to be created and shown immediately afterwards. I am using Thread.sleep() to wait for 3 seconds but the loading page is delayed 3 seconds instead of the game. Code is below:
new load();
try
{
Thread.sleep(3000);
dispose();
new gameInfo();
}
catch (InterruptedException ex)
{
Logger.getLogger(home.class.getName()).log(Level.SEVERE, null, ex);
}
you need to run it on new thread because what you did for now is freezing the main thread and it's affecting the GUI and make it freeze too. So, you need to wait for 3000ms in the background, and the only simply way is make a new thread. here's is the pseudocode
new load();
new Thread(){
public void run(){
try {
Thread.sleep(3000);
//i think you should call this 2 lines below in main thread
dispose();
new gameInfo();
} catch (InterruptedException ex) {
Logger.getLogger(home.class.getName()).log(Level.SEVERE, null, ex);
}
}
}.start();
this code not going to work, this is just the pseudocode. i need to see the whole class to make it able to run.
new load();
new Thread(){
public void run(){
try {
Thread.sleep(3000);
//i think you should call this 2 lines below in main thread
dispose();
new gameInfo();
} catch (InterruptedException ex) {
Logger.getLogger(home.class.getName()).log(Level.SEVERE, null, ex);
}
}
}.start();

Sleep a java thread but update jFrame first

I want to display a text before executing the function mediaPlayer(). During the execution of the mediaplayer, I sleep the thread. That's ok because nothing needs to happen then (then just need to listen).
However, the last text: "Listen to...", is not being displayed (except with a few seconds delay). It there a way to flush the jFrame first before the thread goes to sleep?
expText.setText("Listen to the song and give a rating when it finishes.");
startButton.setEnabled(false);
//play sound
try {
mediaPlayer();
//wait for the duration of the stimuli
Thread.sleep(stimDuration);
...
The setText won't display until the EDT renders another frame, which it can't do because it's busy sleeping for stimDuration amount of time.
Try to play the sound on a separate thread, play the sound on some other thread, detect when the sound stops, and then do another action on the EDT where you change expText back to the original text that you had.
The following combined use of Threads and Swing Timer solved the problem.
Thread t2 = new Thread(new Runnable() {
public void run() {
try {
startButton.setEnabled(false);
startButton.setVisible(false);
buttonsPanel.setEnabled(false);
buttonsPanel.setVisible(false);
expText.setText("Listen to the song and give a rating when it finishes.");
} catch (Exception e1) {
e1.printStackTrace();
}
}
});
t2.start();
Thread t1 = new Thread(new Runnable() {
public void run() {
// code goes here.
try {
mediaPlayer();
// Thread.sleep(5000);
} catch (Exception e1) {
e1.printStackTrace();
}
}
});
t1.start();
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//...Perform a task...
resultButtonGroup.clearSelection();
startButton.setEnabled(true);
startButton.setVisible(true);
buttonsPanel.setVisible(true);
}
};
Timer timer = new Timer(stimDuration ,taskPerformer);
timer.setRepeats(false);
timer.start();

Thread.sleep and hiding buttons

The problem that I have in my code is that when it runs the button.setVisible(true); it won't set the button to visible until all the other if statements are passed through which really confuses me.
I'm trying to make simon says, and what this try-catch does is that it makes the button in the sequence order blink so that the user can know which button it is that follows.
I'm new to programming so any tips and advises are welcome.
Thank you for taking a look!
try {
inputOrder.clear();
// System.out.println("THIS IS INPUT" + inputOrder);
Sequence.add(randomNumber());
int f = 0;
for (; f < Sequence.size(); f++) {
//Thread.sleep(2000);
if (Sequence.get(f) == 1) {
try {`
btnNewButton.setVisible(false);
Thread.sleep(1000);
} catch (InterruptedException e1) {
}
Thread.sleep(1000);
System.out.println("it ran here");
btnNewButton.setVisible(true);
}
if (Sequence.get(f) == 2) {
try {
btnBlue.setVisible(false);
Thread.sleep(1000);
} catch (InterruptedException e1) {
}Thread.sleep(1000);
System.out.println("it ran here");
btnBlue.setVisible(true);
}
if (Sequence.get(f) == 3) {
try {
btnYellow.setVisible(false);
Thread.sleep(1000);
} catch (InterruptedException e1) {
}Thread.sleep(1000);
System.out.println("it ran here");
btnYellow.setVisible(true);
}
if (Sequence.get(f) == 4) {
try {
btnGreen.setVisible(false);
Thread.sleep(1000);
} catch (InterruptedException e1) {
}
Thread.sleep(1000);
System.out.println("it ran here");
btnGreen.setVisible(true);
}
System.out.println(Sequence);
// Order.add(getColor(Sequence.get(f)));
System.out.println(Order);
text.setText(String.valueOf(Order.size()));
}
btnNextRound.setVisible(false);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
Looks like this happens because you are doing this operation in the UI thread, and it does not have time to execute EventQueue since you force to sleep the UI thread, due to this thread gets chance to actually do the paint once it finish all the sleep calls.
In order to get desired output, I think you should move the sleep logic into a separate thread or to a SwingWorker. If you moved the logic to a separate thread you need to use the EventQueue.InvokeLater to enable buttons.
The way that the Java Swing GUI works is that everything happens one after another. Only when the entire method you posted is finished will the next GUI events (such as the repainting events that need to occur to show that the button's not visible anymore). Doing a Thread.sleep just makes your method take longer to finish. The result is that your UI is frozen because no other events (such as mouse, keyboard, or repainting events) are able to run until after all of your sleep calls.
To perform animation in Java, you should use the javax.swing.Timer class rather than using Thread.sleep. Below I've posted a quick example of a timer that, when started, will cause a button to flash. This doesn't completely solve your problem (you're also looping, but you really need another timer to actually schedule when the buttons will flash so that they don't all happen at once).
import javax.swing.Timer
/**
* Timer that causes a button to flash (become invisible for 1 second, and then become visible again).
*/
public class ButtonFlashTimer extends Timer {
private final JButton buttonToFlash;
public ButtonFlashTimer(JButton button) {
super(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// This method is called every 1000 ms (until we tell
// it to stop). This allows us to perform the next "step"
// in the animation.
boolean isVisible = buttonToFlash.isVisible();
if (isVisible) {
buttonToFlash.setVisible(false);
} else {
buttonToFlash.setVisible(true);
// Once we've flashed, stop the timer (don't keep flashing).
stop();
}
}
});
buttonToFlash = button;
// Become invisible immediately; the 1000 ms will be the time between the first
// call to the actionPerformed (which will set it as invisible) and the second
// call (which makes it visible again).
setInitialDelay(0);
setRepeats(true);
}
}

Changing color before removing button

I'm trying to create a button that changes color of the background and then removes itself from the JFrame after a set amount of time, but instead of changing color it just stays pressed for the duration of wait.
public void actionPerformed(ActionEvent e) {
setBackground(Color.red);
try{
Thread.sleep(10000);
}
catch (InterruptedException iE) {
}
frame.remove(this);
}
Can anyone see what im doing wrong?
Your sleep is occurring in the main UI thread, hence the reason the button just stays pressed. If you want a sleep you should create a new thread, get that to sleep, then from within that thread you can get the frame to remove the button.
new Thread() {
public void run() {
try {
Thread.sleep(10000);
// Now do what is needed to remove the button.
} catch (InterruptedException e) {
e.printStackTrace();
}
};
}.start();

Categories

Resources