I am having a problem writing/updating the textarea. I am getting a value from the readtemp function, and i can see the result after calling the system out function, but nothing appears in the Textarea. What could be the problem?
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
URL temp;
try
{
temp = new URL("http://192.168.1.25/status.xml");
while (true)
{
System.out.println("Homerseklet: " + readtemp(temp));
jTextArea1.append(readtemp(temp));
}
}
catch (MalformedURLException ex)
{
Logger.getLogger(Download.class.getName()).log(Level.SEVERE, null, ex);
}
}
Correction: This won't help since the infinite loop will still block the EDT forever... Nevermind!
Your while loop is a really bad idea, but if you insist, you can at least give the EDT a chance to update the UI by dispatching your append asynchronously:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
jTextArea1.append(readtemp(temp));
}
});
Are you doing IO and graphics in separate threads as it's supposed to be done? You should only do updating UI in the event dispatch thread, so when retrieving results from external place has completed you submit the update to event dispatch thread.
The problem exists because of the infinite loop while (true). Because the function jButton1ActionPerformed never ends, Swing has no chance to rerender the jTextArea1 component (I assume that this method is called in AWT Thread).
As mentioned in the previous answers it's a bad idea to handle long-running operations inside the swing thread. As a solution i'd replace your "textfield.append()"- Line with the following code snippet:
Java 8 way:
SwingUtilities.invokeLater(() -> jTextArea1.append(readtemp(temp)));
Pre-Java 8:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
jTextArea1.append(readtemp(temp));
}
});
Source and some explanation: https://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
Related
Hey i just need a question answered...
How would i make the following code not freeze my whole JFrame?
try {
Thread.sleep(Integer.parseInt(delayField.getText()) * 1000);
System.out.println("Hello!");
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
use a different thread to perform this task. If you do this in the main UI thread then it will freeze.. For example you can do following
new Thread() {
#Override
public void run() {
try {
Thread.sleep(Integer.parseInt(delayField.getText()) * 1000);
System.out.println("Hello!");
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}.start();
UPDATE
AFter wise suggestions of Robin and Marko I am updating the answer with a better solution.
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
System.out.println("Hello!");
}
};
javax.swing.Timer t = new javax.swing.Timer(Integer.parseInt(delayField.getText()) * 1000, taskPerformer);
t.setRepeats(false);
t.start();
Whenever you are about to use Thread.sleep in your GUI code, stop yourself and think of Swing Timer, which is the right tool for the job. Schedule the task you need to perform with a delay.
Using another thread for this is not the best advice: it wastes a heavy system resource (a thread) to do absolutely nothing but wait.
This is not the correct way to use threads in java . You should use swingutilities.invokelater
swing utils invoke later
You don't want to execute this on the UI (or event dispatch thread) thread. Rather in a separate thread. Otherwise (as you've seen) you'll block the UI.
It's a good practice to perform time-consuming operations on a separate thread, and make use of SwingUtilities.invokeLater() if those threads need to perform some subsequent UI action (e.g. in the above display "Hello" in the UI)
Hey i just need a question answered...
How would i make the following code not freeze my whole JFrame?
try {
Thread.sleep(Integer.parseInt(delayField.getText()) * 1000);
System.out.println("Hello!");
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
use a different thread to perform this task. If you do this in the main UI thread then it will freeze.. For example you can do following
new Thread() {
#Override
public void run() {
try {
Thread.sleep(Integer.parseInt(delayField.getText()) * 1000);
System.out.println("Hello!");
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}.start();
UPDATE
AFter wise suggestions of Robin and Marko I am updating the answer with a better solution.
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
System.out.println("Hello!");
}
};
javax.swing.Timer t = new javax.swing.Timer(Integer.parseInt(delayField.getText()) * 1000, taskPerformer);
t.setRepeats(false);
t.start();
Whenever you are about to use Thread.sleep in your GUI code, stop yourself and think of Swing Timer, which is the right tool for the job. Schedule the task you need to perform with a delay.
Using another thread for this is not the best advice: it wastes a heavy system resource (a thread) to do absolutely nothing but wait.
This is not the correct way to use threads in java . You should use swingutilities.invokelater
swing utils invoke later
You don't want to execute this on the UI (or event dispatch thread) thread. Rather in a separate thread. Otherwise (as you've seen) you'll block the UI.
It's a good practice to perform time-consuming operations on a separate thread, and make use of SwingUtilities.invokeLater() if those threads need to perform some subsequent UI action (e.g. in the above display "Hello" in the UI)
Hey i just need a question answered...
How would i make the following code not freeze my whole JFrame?
try {
Thread.sleep(Integer.parseInt(delayField.getText()) * 1000);
System.out.println("Hello!");
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
use a different thread to perform this task. If you do this in the main UI thread then it will freeze.. For example you can do following
new Thread() {
#Override
public void run() {
try {
Thread.sleep(Integer.parseInt(delayField.getText()) * 1000);
System.out.println("Hello!");
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}.start();
UPDATE
AFter wise suggestions of Robin and Marko I am updating the answer with a better solution.
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
System.out.println("Hello!");
}
};
javax.swing.Timer t = new javax.swing.Timer(Integer.parseInt(delayField.getText()) * 1000, taskPerformer);
t.setRepeats(false);
t.start();
Whenever you are about to use Thread.sleep in your GUI code, stop yourself and think of Swing Timer, which is the right tool for the job. Schedule the task you need to perform with a delay.
Using another thread for this is not the best advice: it wastes a heavy system resource (a thread) to do absolutely nothing but wait.
This is not the correct way to use threads in java . You should use swingutilities.invokelater
swing utils invoke later
You don't want to execute this on the UI (or event dispatch thread) thread. Rather in a separate thread. Otherwise (as you've seen) you'll block the UI.
It's a good practice to perform time-consuming operations on a separate thread, and make use of SwingUtilities.invokeLater() if those threads need to perform some subsequent UI action (e.g. in the above display "Hello" in the UI)
I need to update jProgressBar in method which read from file and do some operations.
I tried to update progress bar by this method:
public void progressUpdate(int percent) {
System.out.println("Update = "+percent);
synchronized (jMainProgressBar) {
jMainProgressBar.setValue(percent);
}
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
jMainProgressBar.updateUI();
jMainProgressBar.repaint();
}
});
}
how ever this works only then when method is done. But if i continuously updating by this method then nothing happens.
Maybe some know how to improve this method?
It also would be nice for more suggestion Worker thread and else.
You probably want to do
public void progressUpdate(final int percent) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
jMainProgressBar.setValue(percent);
}
});
}
Don't use Thread. Use Timer. Refer the following:
JProgressBar in Napkin look and feel is not working
How to Use Progress Bars
http://www.roseindia.net/java/example/java/swing/SwingProgressBar.shtml
Read Concurrency in Swing for more information
Based on the comments you provided (but not from the question!) you are performing heavy work on the Event Dispatch Thread (EDT). This blocks that thread and avoids any scheduled repaints to be performed. That is why you only see the update of your JProgressBar after the work is finished, as that is the moment the EDT becomes available to perform the repaint.
The solution is already provided in the links posted by others but it basically comes down to:
perform the work on a worker thread
update the progress on the JProgressBar on the EDT
The two most common ways to achieve this are using a SwingWorker or using SwingUtilities.invokeLater from the worker thread.
All relevant links can be found in the answer of Yohan Weerasinghe
Check this out
Timer barTimer;
barTimer=new Timer(100,new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
barvalue++;
if(barvalue>jProgressBar1.getMaximum())
{
/*
* To stop progress bar when it reaches 100 just write barTime.stop()
*/
barTimer.stop();
barvalue=0;
}
else
{
int a=(int)jProgressBar1.getPercentComplete();
jProgressBar1.setStringPainted(true);
jProgressBar1.setValue(barvalue);
}
}
});
barTimer.start();
Check the code at this link
http://java23s.blogspot.in/2015/10/how-to-implement-progress-bar-in-java.html
So my program has multiple classes and after one of them has run, it'd like it so it appends the text area in the main class GUI with a 'finished' message
ta.append("Search Complete\n");
and this is the code that needs to complete
statCl.addActionListener(new ActionListener(){
public void actionPerformed (ActionEvent e) {
try {
ta.append("Searching...\n");
task.execute();
} catch (Exception IOE) {}
}
});
So it is in the class where task where actual code runs.
Any advice or help would be amazing, thanks.
If the task.execute() method doesn't start launch an operation in another thread, then the GUI will be freezed, and nothing will apear in the text area until the operation is finished. So you might just have
ta.append("Searching...\n");
task.execute();
ta.append("Finished");
If the operation is launched in a new thread, then this thread should append in the text area, but it should make sure this append is done in the event dispatch thread (EDT). Your code could thus look like this :
public class Task {
private JTextArea ta;
public Task(JTextArea ta) {
this.ta = ta;
}
public void execute() {
Thread t = new Thread(new Runnable() {
// perform the long operation
// at the end, update the text area, in the EDT
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ta.append("finished");
}
});
}
t.start();
}
}
You might also look at SwingWorker, which is designed just for that (and other things like progress update). There is a code example in its class javadoc which does just what you're trying to do.
You should not be performing long-running task on EDT (event dispatching thread):
http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html
Swing does all it's work on EDT, so you should not block EDT, e.g. run intensive tasks on it. Note: all event handlers are executed on EDT.
So there are two challenges:
Run intensive tasks in a background thread.
Update GUI, which must be done on EDT.
Use SwingWorker to solve this two issues.