Swing: Enabling Buttons With Delay - java

private void OptionsActionPerformed(java.awt.event.ActionEvent evt)
{
// After clicking on button X, I want 4 other buttons to show up
// in a sequential order
ButtonTrue();
}
public void ButtonTrue()
{
Audio_Options.setVisible(true);
letsSleep();
Control_Options.setVisible(true);
letsSleep();
Display_Options.setVisible(true);
letsSleep();
Network_Options.setVisible(true);
}
public void letsSleep()
{
try {
Thread.sleep(10000);
} catch (InterruptedException ex) {
Logger.getLogger(MainMenu.class.getName()).log(Level.SEVERE, null, ex);
}
}
I have 4 buttons. I want them to appear in a sequential order such as :
Button1 - 10seconds - Button2 - 10 seconds - Button3 - 10seconds - Button 4
Problem: Whenever I call the function "ButtonTrue()", they all appear together after waiting 30 seconds. What can cause this problem to occur?

don't use Thread.sleep(int) for Swing JComponent, because blocking current EDT
you have look at Swing Timer

You should use different Threads for this:
javax.swing.Timer timer = new Timer(10000, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//...Update the progress bar...
Control_Options.setVisible(true);
timer.stop();
}
});
timer.start();
Your buttons have to be final to be in scope for the anonymous ActionListener.

I think the problem is that all setVisble invocations are within one thread, which isn't EventDispatchThread. You could try calling:
if(EventQueue.isDispatchThread()) {
ButtonTrue();
} else {
EventQueue.invokeAndWait(new Runnable() {
ButtonTrue();
});
}

Related

I am a beginner and I am trying to make a card flip game in netbeans

On clicking an image I want another image to be displayed pause for one second and the original image to be restored and displayed againdisplayed again When I try to do it it action handler such as code given below it sets the image after sleep .I want the image to be displayed pause and the original to be displayed again how can I achieve that
private void jButton16ActionPerformed(java.awt.event.ActionEvent evt) {
jButton16.setIcon(new javax.swing.ImageIcon("C:\\Users\\x\\Documents\\O.png"));
try { //sleep 1 seconds
Thread.sleep(1000);
}
catch (InterruptedException e)
{
}
jButton16.setIcon(new javax.swing.ImageIcon("C:\\Users\\x\\Documents\\118px-AMIGO.jpg")); }
Swing is single threaded, you should never perform long running or blocking operations within the context of the Event Dispatching Thread
Swing is NOT thread safe, this means you should never update the UI (and anything the UI needs) outside of the context of the EDT
The simplest solution to your problem is to use a Swing Timer
private void jButton16ActionPerformed(java.awt.event.ActionEvent evt) {
jButton16.setIcon(new javax.swing.ImageIcon("C:\\Users\\x\\Documents\\O.png"));
Timer timer = new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
jButton16.setIcon(new javax.swing.ImageIcon("C:\\Users\\x\\Documents\\118px-AMIGO.jpg"));
}
});
timer.setRepeats(false);
timer.start();
}
See Concurrency in Swing and How to use Swing Timers for more details
You should never invoke Thread.sleep() inside Event Dispatch Thread
because Thread.sleep() will block Event Dispatch Thread and your UI will be Freeze , instead you could use a Timer to achieve your goal
Refer below code,
jButton16.setIcon(new javax.swing.ImageIcon("C:\\Users\\x\\Documents\\O.png"));
Timer timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
jButton16.setIcon(new javax.swing.ImageIcon("C:\\Users\\x\\Documents\\118px-AMIGO.jpg"));
}
});
timer.setRepeats(false);
timer.start();

Best way to make a thread start from a jbutton?

I have 15 different threads running all with dynamic input from the user. I need these Threads to run ONLY when my JButton is pressed. I know i didnt supply the code for the button but its just a simple deceleration.
JButton JButton_Button1 = new JButton("Start");
To clarify one more time i just want the thread to start only when JButton_Button1 is clicked
new Thread() {
int counter = 10;
public void run() {
while(counter >= 0) {
JLabel_MistyvaleLoot.setText("Test" + (counter--));
try{
Thread.sleep(1000);
} catch(Exception e) {}
}
}
}.start();
If you're looking to have 15 threads running, but you want them to do nothing except when a JButton is pressed, then consider using a fixed-size thread pool. Try using:
private ExecutorService threadPool = Executors.newFixedThreadPool(15);
This constructs 15 processing threads that will idle until you submit a task. If you are looking to submit a task when the JButton is pressed, then you should add an ActionListener. That is, try this:
JButton jButton1 = new JButton("Start");
jButton1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event){
threadPool.submit(new Runnable(){
int counter = 10;
public void run() {
while(counter >= 0) {
JLabel_MistyvaleLoot.setText("Test" + (counter--));
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
}
}
}
});
}
});
To get one of the fifteen threads to run the task, you call threadPool.submit() and to get the button to respond to a click, you call jButton1.addActionListener().

Do Java Swing action on specified Date

I'm trying to create a program which has two options:
- Do specific task after countdown (in minutes).
- Do specific task on the date selected.
Both are using jSpinners however, I don't know how to do the action on the specific date, here's the code below, thank you in advance!
protected Object doInBackground() throws Exception {
Timer t = new Timer(0, new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
//Checking state of CheckBoxes (one cancels the other)
if(jCheckBox2.isSelected()) {
try {
int delay =(int) jSpinner2.getValue();
jCheckBox1.setSelected(false);
Thread.sleep(delay*60000); //To delay the code from miliseconds to minutes
} catch (InterruptedException ex) {
Logger.getLogger(App_Gui.class.getName()).log(Level.SEVERE, null,
ex);
}
}
else if (jCheckBox1.isSelected()) {
Date delay2 = (Date) jSpinner1.getValue();
jCheckBox2.setSelected(false);
Thread.sleep(delay2); //What should I put here instead of Thread.sleep()???????
}
//If all is right, start the timer
t.start();
t.setRepeats(false);
//Popup dialog
JDialog dialog = new JDialog();
dialog.setLocation(700, 300);
dialog.setSize(600, 400);
dialog.setVisible(true);
//Speed of color changing
try {
Thread.sleep(jSlider1.getValue());
} catch (InterruptedException ex) {
Logger.getLogger(App_Gui.class.getName()).log(Level.SEVERE, null,
ex);
} //Setting the color
dialog.getContentPane().setBackground(jLabel2.getBackground());
dialog.setModal(true);
Assignment_Tajmer_Aplikacija.f.setVisible(false);
return null;
}
protected void done() {
System.out.println("Done!");
}
};
sw.execute();
}
private void jSlider1StateChanged(javax.swing.event.ChangeEvent evt) {
// TODO add your handling cosadde here:
jSlider1.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
JSlider source = (JSlider) e.getSource();
//System.out.println(source.getValue());
}
});
}
You have 2 choices:
You compute time difference in milliseconds between current date and target date. So you can start the swing timer. Something like myDate.getTime() - Sytem.currentTimeMillis() (it's probably not always correct)
You use a Library which do it for you (for example Quartz). In this case you need to synchronize your job with the Swing thread using the method SwingUtilities.invokeLater(Runnable).
And never use Thread.sleep() in a Swing application. Start a timer instead.

strange bug - how to pause a java program?

I'm trying to:
display a text in a jLabel,
wait for two seconds,
then write a new text in the jLabel
this should be simple, but I get a strange bug:
the first text is never written, the application just waits for 2 seconds and then displays the final text. here is the example code:
private void testButtonActionPerformed(java.awt.event.ActionEvent evt) {
displayLabel.setText("Clicked!");
// first method with System timer
/*
long t0= System.currentTimeMillis();
long t1= System.currentTimeMillis();
do{
t1 = System.currentTimeMillis();
}
while ((t1 - t0) < (2000));
*/
// second method with thread.sleep()
try {
Thread.currentThread().sleep(2000);
} catch (InterruptedException e) {}
displayLabel.setText("STOP");
}
with this code, the text "Clicked!" is never displayed. I just get a 2 seconds - pause and then the "STOP" text.
I tried to use System timer with a loop, or Thread.sleep(), but both methods give the same result.
Just to provide more background on Andrew Thompson's comment: the EDT is responsible for handling gui updates. If you block it using Thread.sleep(...) those updates are blocked as well. That's why you don't see the first text - the EDT just can't do the update on the label.
Here's a runnable example which does what you're after. As Andrew Thompson's comment stated, a SwingWorker is a good way to approach this problem.
The basic principal is to never block the Event Dispatch Thread. That's the thread responsible for repainting the GUI and responding to user interaction, so if you do something computationally expensive on the EDT, your GUI will stop responding.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.ExecutionException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingWorker;
public class ButtonTest {
public static void main(String[] args) {
// create a frame and a button
JFrame frame = new JFrame();
final JButton button = new JButton("Button");
frame.add(button);
// add an action listener to the button
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// change the button text right away
button.setText( "Clicked" );
// create a SwingWorker which simply waits 2000 milliseconds
// simulating a computation being performed
SwingWorker<String, Object> worker = new SwingWorker<String, Object>() {
#Override
public String doInBackground() {
// it's safe to call Thread.sleep( ) here
// doInBackground is executed on a separate worker
// thread
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
return "Done";
}
#Override
protected void done() {
// done() is executed back on the Swing thread
// so it's safe to updated the state of the button
try {
button.setText(get());
} catch (Exception e) { }
}
};
// run the worker
worker.execute();
}
});
frame.setSize( 300, 300 );
frame.setVisible( true );
}
}
You are messing with the event dispatcher thread.
That will cause un-expected UI behavior as you are seeing. If you plan to do these type of animations, make sure to read up on what #Andrew Thompson suggested and also, see if you can read this - Filthy rich clients
Better to use a Swing Timer as shown in curde-example below:(yes, it is crude, I did not worry about stopping the timer etc):
public class DelayTest extends JPanel{
JLabel messageLabel = new JLabel();
JButton actionButton = new JButton("Click Me");
String[] messages = {"Clicked", "Stop!"};
int i=0;
public DelayTest(){
super();
add(messageLabel);
add(actionButton);
actionButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
Timer timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
if(i<=1)
messageLabel.setText(messages[i++]);
}
});
timer.start();
}
});
}
}
Edit
Why not stop the Timer:
#Override
public void actionPerformed(ActionEvent evt) {
if (i <= 1) {
messageLabel.setText(messages[i++]);
} else {
((Timer)evt.getSource()).stop();
}
}
});

How to Delay MessageDialogBox in Java?

So in this chunk of code:
//Actions performed when an event occurs.
public void actionPerformed(ActionEvent event)
{
String command = event.getActionCommand();
//If btnConvertDocuments is clicked, the FileConverter method is called and the button is then disabled [so as to prevent duplicates].
if (command.equals("w"))
{
new Thread(new Runnable()
{
public void run()
{
FileConverter fc = new FileConverter();
}
}).start();
btnConvertDocuments.setEnabled(false);
//Validation message ensuring completion of the step.
JOptionPane.showMessageDialog(this, "Step 1 Complete!", "Validation", JOptionPane.INFORMATION_MESSAGE);
}
It seems like the message dialog window pop-ups way too fast, before the FileConverter method isn't even finished being called. I was wondering if the placement of JOptionPane was correct, or if there was a way to delay a message until the method finished processing?
You can use the SwingWorker.
Have a look here, java tutorial.
SwingWorker worker = new SwingWorker<Void, Void>() {
#Override
public Void doInBackground() {
FileConverter fc = new FileConverter();
return null;
}
#Override
public void done() {
JOptionPane.showMessageDialog(this, "Step 1 Complete!", "Validation", JOptionPane.INFORMATION_MESSAGE);
}
};
You should use a Swing Timer with a delay, instead of using your own Thread and Runnable for this.
You can use Swing timers in two ways:
To perform a task once, after a delay.
For example, the tool tip manager uses Swing timers to determine when to show a tool tip and when to hide it.
To perform a task repeatedly.
For example, you might perform animation or update a component that displays progress toward a goal.
An example from the documentation:
int delay = 1000; //milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//...Perform a task...
}
};
Timer myTimer = new Timer(delay, taskPerformer);
myTimer.setRepeats(false);
myTimer.start();

Categories