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();
Related
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
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();
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);
}
}
I have a jList called todoList
When the user click on an item in the list, it stays selected. But I would like the currently selected item in the list to deselect "by itself" after 400 milliseconds when the mouse exits the jList.
This must only run if there is something already selected in the list.
I am using Netbeans IDE and this is what is have tried so far:
private void todoListMouseExited(java.awt.event.MouseEvent evt) {
if (!todoList.isSelectionEmpty()) {
Thread thread = new Thread();
try {
thread.wait(400L);
todoList.clearSelection();
} catch (InterruptedException ex) {
System.out.println(ex);
}
}
}
and
private void todoListMouseExited(java.awt.event.MouseEvent evt) {
if (!todoList.isSelectionEmpty()) {
Thread thread= Thread.currentThread();
try {
thread.wait(400L);
todoList.clearSelection();
} catch (InterruptedException ex) {
System.out.println(ex);
}
}
}
These both just make everything stop working.
My though process was that i need to create a new Thread that will wait for 400 milliseconds and then run the clearSelection() method of the jList. This would happen every time the mouse exits the list and run only if there is something in the list that is already selected.
I hope I am explaining my problem thoroughly enough.
The problem is that you are blocking the AWT-Event-Thread.
The solution is to use a swing timer:
private void todoListMouseExited(java.awt.event.MouseEvent evt)
{
if (!todoList.isSelectionEmpty()) {
new Timer(400, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
todoList.clearSelection();
}
}).start();
}
}
The problem is that Object#wait is waiting(rather than sleeping) to be notified but this is not happening. Instead the timeout causing an InterruptedException bypassing the call to clearSelection.
Don't use raw Threads in Swing applications. Instead use a Swing Timer which was designed to interact with Swing components.
if (!todoList.isSelectionEmpty()) {
Timer timer = new Timer(400, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
todoList.clearSelection();
}
});
timer.setRepeats(false);
timer.start();
}
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.