Update JTextFields text every 3 seconds after pressing button - java

So what I want to do is that when I press button JTextField text starts to update to new value every 3 seconds. I have tried Thread sleep metod, but it freezes whole program for the sleep time and after it is over textfields gets the latest input. So here is better explained example of what i am trying to do.
I press the JButton which puts the numbers in JTextFiel every 3 seconds as long as there is available values. I dont want it to append new text, just replace old with new. Anyone got ideas how I can do that? Thanks in advance.

You should use a javax.swing.Timer.
final Timer updater = new Timer(3000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
// update JTextField
}
});
JButton button = new JButton("Click me!");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
updater.start();
}
});
The Timer will not block the Event Dispatch Thread (like Thread.sleep does) so it won't cause your program to become unresponsive.

You can't sleep in the EDT. You can either use a swingworker (better solution) or do something like this:
//sleep in new thread
new Thread (new Runnable() {
public void run() {
Thread.sleep(3000);
//update UI in EDT
SwingUtilities.invokelater(new Runnable() {
public void run() {updateYourTextHere();}
});
}
}).start();

You need to get 'the work' done on a separate thread. See some of the answers here: Java GUI Not changing

Related

How do you update a JLabel before a delay?

When I try to use any kind of delay on my code the program gets delayed but the JLabel that was put before the delay gets updated after the program ends.
I want the program to:
update the JLabel on the GUI
wait for 5 seconds
update the JLabel again with diferent text
wait another 5 seconds
I have tried with timers, invokelater, invokeandwait, thread.sleep and others.
The problems is that the GUI does get delayed at the right spot but the GUI does not update the JLabel ath place where the code is located. The JLabel gets updated after the program ends.
I want the user to be able to read the text for 5 seconds then read another text for another 5 seconds in order. I do not want the program to run the gui pause at a cetain spot then at end just update the JLabel. I want the gui to get updated before the delay. I do not want the same thing that when I used a timer to happen where I type in a setText for the JLabel before the Timer is typed and then when I run the program the timer works but the JLabel gets updated after the delay(It is not what I want).
The way to achieve that is either using a Swing Worker, either a a Swing Timer. A Swing worker runs a task in background and at the same time it is capable of publishing GUI changes in the Event dispatch thread (the thread where the GUI runs). A SwingTimer can be considered as a simplified version of a Swing Worker, that only runs a task after some time in the Event Dispatch Thread. (Consider a worker that sleeps the thread in background, and after the sleep, it runs the task in the Gui thread).
There are a lot of examples online, like this one and this one.
If you do not want to do something in background, a Timer solution sounds "simpler". Take a look at How can I pause/sleep/wait in a java swing app?
An example where it is closer to what you need (with a worker):
public class WorkerExample extends JFrame {
private static final long serialVersionUID = 6230291564719983347L;
private JLabel label;
public WorkerExample() {
super("");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new FlowLayout());
SwingWorker<Void, String> worker = new SwingWorker<Void, String>() {
#Override
protected Void doInBackground() throws Exception {
publish("Started....");
Thread.sleep(1500);
for (int i = 0; i < 5; i++) {
publish("Number of iterations: " + i);
//Do something
Thread.sleep(3500);
}
return null;
}
#Override
protected void process(List<String> chunks) {
String chunk = chunks.get(0);
label.setText(chunk);
}
#Override
protected void done() {
label.setText("Done.");
}
};
JButton button = new JButton("Start");
button.addActionListener(e -> worker.execute());
add(button);
label = new JLabel("Nothing yet.");
add(label);
setSize(400, 400);
setLocationByPlatform(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new WorkerExample().setVisible(true);
});
}
}
You can experiment with these in order to understand how a SwingWorker works, but I strongly recommend you to read concurrency in Swing before doing that.

Main Thread freezes all other threads inclusive java gui thread

NOTE: I work a lot of hours and research google and stackoverflow but I cannot find answer.
I use Thread.sleep() in a JDialog and it freezes all other JDialog, JFrame and threads.
My example code:
public Guitest()
{
setSize(300,300);
// create a JDialog that make guitest wait
MyDialog dlg = new MyDialog();
dlg.setSize(100,100);
dlg.setVisible(true);
while(dlg.isWait())
{
try
{
Thread.sleep(1000);
} catch (InterruptedException ex)
{
Logger.getLogger(Guitest.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("waiting mydialog");
}
}
class MyDialog extends JDialog
{
boolean wait = true;
JButton btn = new JButton("OK");
public MyDialog()
{
setSize(50,50);
btn.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
wait=false;
}
});
add(btn);
}
public boolean isWait()
{
return wait;
}
}
In this situation JDialog does not appear correctly:
inccorect appear jdialog
But it must be apper this:
true appear jdialog
How can I solve this problem. I want to make main thread wait another thread.And someone can correct my sample code or share a sample code with this situation.
IMHO, it appears like you have just one running thread. At first, we draw our JDialog, after that, you sleep your main thread because of the wait flag.
ie. you can't execute your button action listener, thus you can't awake your thread.
Hope it helps understanding.
Thread.Sleep() just sleeps the current thread (i.e. stops it from doing anything, such as redrawing, processing clicks etc), which in your case is the UI thread.
You need to use a worker thread. Any main work that needs to be done that may take a larger amount of time needs to be done in its own thread, and this is the thread that you will want to sleep. It is currently ran alongside the UI components and so this is why you're seeing them freezing.
A good reference is the documentation for concurrency for swing http://docs.oracle.com/javase/tutorial/uiswing/concurrency/
The following may be useful too:
http://java.sun.com/developer/technicalArticles/Threads/swing/
http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html

Multiple Actions in a JButton

In this program, we are supposed to click a button that says "Start" and then the animation will start running across the screen. After we click "Start," the button then changes to a "Pause" button where if you click it, it stops the animation and a "Resume" button appears. I am not sure how to get all three of those actions into one button. Here is the code I have so far:
JButton button = new JButton("Start");
button.addActionListener(new
ActionListener()
{
public void actionPerformed(ActionEvent e)
{
Timer t = new Timer(100, new
ActionListener()
{
public void actionPerformed(ActionEvent event)
{
shape.translate(x, y);
label.repaint();
}
});
t.start();
}
});
I know this isn't right. When I run the program, the animation is idle until I hit "Start" which is correct, but then every time I hit the button again, the animation speeds up which is not correct. How do I go about adding different actions to the button?
For instance after the animation is running, I want the "Pause" button to stop the Timer when it is clicked, then to resume the Timer when I hit "Resume." The code I have now creates a new Timer object every time I click it, but this seems to be the only way I get it to work. If I put anything outside the ActionListener, I get a scope error. Any suggestions?
I know this isn't right. When I run the program, the animation is idle until I hit "Start" which is correct, but then every time I hit the button again, the animation speeds up which is not correct.
This is because you're creating multiple new Timers each time you press the button. You should have a single reference to the Timer and be making decisions about what to do based on it's current state
//...
private Timer timer;
//...
JButton button = new JButton("Start");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (timer == null) {
timer = new Timer(100, new ActionListener() {
public void actionPerformed(ActionEvent event) {
shape.translate(x, y);
label.repaint();
}
});
timer.start();
button.setText("Pause");
} else if (timer.isRunning()) {
timer.stop();
button.setText("Resume");
} else {
timer.start();
button.setText("Pause");
}
}
});
but then every time I hit the button again, the animation speeds up which is not correct.
Don't keep creating a Timer in the ActionListener. Every time you click the button you start a new Timer.
Instead create the Timer in the constructor of your class. Then in the ActionListener you just start() the existing Timer.
Then the Pause and 'Resumebuttons will also just invoke thestop()andrestart()` methods on the existing Timer as well.

How to implement a delay in ActionListener in Swings?

I have a Swing application where I wish to add some delay. I have a close button, which on clicking should display the JTextArea which displays "Closing database connections...." and then execute Database.databaseClose() method and System.exit(). I have tried using Thread.sleep() method as in the code below for the delay. When I execute the program, the screen freezes for 2 seconds and then closes without displaying the JTextArea. The close button and JTextArea is added to JFrame directly.
What I want is that on clicking the close button, the JTextArea should be displayed immediately and then the application should delay for 2 seconds before finally implementing the Database.databaseClose() method and exiting the program. The Database.databaseClose() method works just fine.
I am a beginner at Swings and would greatly appreciate it if anyone could modify the code to implement the requirement above. Thanks!
Here's the code snippet:
JButton btnClose = new JButton("Close");
btnClose.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
JTextArea txtrClosingDatabaseConnections = new JTextArea();
txtrClosingDatabaseConnections.setText("\r\n\tClosing database connections....");
getContentPane().add(txtrClosingDatabaseConnections);
validate();
repaint();
/*
try
{
Thread.sleep(2000);
}
catch (InterruptedException e2)
{
e2.printStackTrace();
}
*/
try
{
Database.databaseClose();
}
catch (Exception e1)
{
e1.printStackTrace();
}
System.exit(0);
}
});
getContentPane().add(btnClose);
Hej, this is an example method that initializes an JMenuBar on a JFrame in Swing.
private JMenuBar initMenuBar() {
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
exitApp = new JMenuItem("Exit App");
exitApp.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Timer t = new Timer(2000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
JOptionPane.showMessageDialog(getParent(), "Closing App in 2 Seconds");
t.start();
}
});
fileMenu.add(exitApp);
menuBar.add(fileMenu);
return menuBar;
}
May it will help you. It creates an JOptionPane, which must be closed by clicking OK, then the JFrame will be closed after 2 seconds.
Your code is executing on the Event Dispatch Thread, so you can't use a Thread.sleep() since that will block the EDT and prevent it from repainting the GUI.
You need to use a separate Thread for you database processing. Read the section from the Swing tutorial on Concurrency for more information as well as a solution that uses a SwingWorker to manager this Thread for you.
The Timer is the solution. The Swing timer's task is performed in the event dispatch thread. This means that the task can safely manipulate components, but it also means that the task should execute quickly.
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.
Please go through http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html for more details.

How to execute several methods one after another in EDT (Swing)

I have 100 same JPanels, each contains JLabel with an icon and JLabel with text. When certain event occurs, I want to change icon and border of panel for 2.5 seconds, and then change them back. The problem is that 1st they are changed together, but when I try to change them back - first icon is changed, and then in 2 or 3 seconds border is changed. Here is the method of a JPanel to perform this:
public void showPacketCame() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
img.setIcon(blue);
setBorder(BorderFactory.createLineBorder(new Color(54, 208, 243)));
javax.swing.Timer tim = new javax.swing.Timer(2500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
img.setIcon(onDark);
setBorder(null);
}
});
tim.setRepeats(false);
tim.setDelay(2500);
tim.start();
}
});
}
This is not the apt way of coding animation task. Please make use of SwingWorker
for this purpose.

Categories

Resources