How to get GUI to update while program is running? - java

I am trying to get the GUI to update after each iteration of the loop. I have read other answers to similar questions and still can't get it to work. In the code below I call simulate which runs through the loop calling step which calculates and changes GUI components as needed but the GUI isn't updating until after the loop completely ends. How can I get it to update after each iteration?
public void step(View v) {
for (int i = 0; i < cells.length; i++)
update(i);
count++;
Toast.makeText(getApplicationContext(), count + "", 1000).show();
}
public void simulate(View v) {
while (!pause) {
step(v);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void update(final int i)
{
//This goes through each button and counts the neighbors (this is the
//intensive work
int neighbors = getNeighbors(i);
//With the information provided from the getNeighbors the following if
//statement updates the GUI using the dead and alive method calls.
if (isAlive(cells[i])) {
if (neighbors < 2)
dead(cells[i]);
else if (neighbors > 3)
dead(cells[i]);
}
else {
if (neighbors == 3)
alive(cells[i]);
}
}

The problem is that you are running that code in the main thread of your application. The GUI runs on the same thread and can not be updated while you are blocking it.
You have to do the calculations in a different task and then send a message to the main process to update the GUI.
Read this for background-information (if you are new to this, you have read the backgrounds first):
http://developer.android.com/guide/topics/fundamentals/processes-and-threads.html
The easiest way to do this is to use AsyncTask and then do the GUI update with "onProgressUpdate()".
Although AsyncTask already makes things pretty easy, you have to mind that the underlying activity can be destroyed while AsyncTask is running. This is not really well covered in the documentation but I find that the use of Fragments is probably the best way of dealing with it. Read this article for a quite nice description:
http://blogactivity.wordpress.com/2011/09/01/proper-use-of-asynctask/
Remark: read also the AsyncTask documentation. I could not post the link due to restrictions of the forum.

We are always adviced that , UI work should be on the UI-Thread, and Non-UI work on Non-UI Thread, but from HoneyComb android version it became a LAW. When we start an application in Android, it start on the Dedicated UI thread, creating any other thread will drop you off the UI thread, you normally do this to do some process intensive work, but when you want to display the output of the non-ui thread process, on the ui thread then you will experience lagging, exception etc...
From my view this can be done in two ways....
Using Handler... Handler stores the reference of the thread on which it was created, Initialize Handler inside the onCreate() method, and then use handler.post() to update the UI thread.
Use AsyncTask<> provided by android, it synchronizes the UI and Non-UI threads
Methods in AsyncTask<>
doInBackground(String...) // Work on the Non-UI thread
postExecute(String result) // Getting the Output from the Non-Ui thread and
Putting the Output back on the UI Thread

I think you have to use AsyncTask for this.
Try to read the documentation..
http://developer.android.com/reference/android/os/AsyncTask.html

Related

Swing: Running code immediately vs invokeLater

I'm currently working with a thread control class someone else wrote. It is used for a java swing application. I have two methods, but I am confused as to why I am getting different behaviors from both. From what I know and read about the event dispatcher thread and Swing, there should be no difference in the two methods below. Apparently, this is not true.
//If this is the AWT Event Processing thread then run the code immediately,
//otherwise schedule it for later processing
public static void runWithEventThread(Runnable r)
{
if (EventQueue.isDispatchThread())
{
r.run();
}
else
{
EventQueue.invokeLater(r);
}
}
//Schedule the runnable for later processing by the AWT Event Queue
public static void runLaterWithEventThread(Runnable r)
{
EventQueue.invokeLater(r);
}
When using runWithEventThread() to display popups while updating GUI (new buttons/repainting), I found that the GUI would mess up sometimes. However when using runLaterWithEventThread(), it was all fine, no issues.
Only problem is that when using runLaterWithEventThread() I found that when I had multiple popups that would be displayed one after the other (after OK clicked) all popups were displayed at once.
From what I understand, both the methods should be doing the same thing. Can someone please explain what is going on
If your first method is executed from the event thread, it MAY act differently than the second method: If there are any events currently waiting on the event thread, those events will be processed BEFORE your run() method is executed if you use the second method, but if you use the first method, your run() method will be executed immediately, and any existing events on the queue will be run AFTER your run() method finishes.

java thread not interrupt when running many thread

My project run on java swing there are 2 button (start/stop) for counting.
When I click start button. There is one thread running (Thread-0) ,then click stop button "Thread-0" disappear but when I click start button many times. there are many threads such as Thread-5, Thread-6, .. Thread-10 are running.
Problem :
If click start and then stop counting is ok. but click start many times it's incorrect counting.
start button
private void btnStartActionPerformed(java.awt.event.ActionEvent evt) {
start();
btnStart.setEnabled(false);
btnStop.setEnabled(true);
}
stop button
private void btnStopActionPerformed(java.awt.event.ActionEvent evt) {
isEnable = false;
btnStop.setEnabled(false);
btnStart.setEnabled(true);
}
start() method :
isEnable = true;
Thread refreshPlan = new Thread() {
#Override
public void run() {
while(isEnable) {
try {
sleep(CYCLE_TIME * 1000);
PLAN += 1;
planValue.setText(String.valueOf(PLAN));
} catch (InterruptedException ex) {
//ignore
}
}
};
};
refreshPlan.start();
Can I run only single thread when click many times in start button ?
any suggestion? thanks.
sorry for my bad english.
There are four significant problems here:
Unless isEnable is declared as a volatile variable, there's no guarantee that a write from one thread will be seen in another thread
Likewise your access to the PLAN counter (which is badly named - please follow Java naming conventions) is unsafe. You may wish to consider using AtomicInteger for this.
You're making changes to the UI from your extra thread. You can't do that - in Swing (and most UIs) all access to UI components has to be done on the thread responsible for that UI. See the Swing concurrency tutorial for more details.
Because you only check isEnabled one per second, it would be possible to stop and start multiple threads in the meantime... leading to several threads being active at once. This could interfere with your counting.
You might find it's better to use a javax.swing.Timer which fires once a second, and just checks whether or not it's meant to do anything. That way everything can be on the UI thread.
start method is instantiating new Thread() that's why every time u click it, it brings new thread into life.
declare Thread refreshPlan class variable then in start method put all the code in this check
if(refreshPlan == null || !refreshPlan.isAlive()){
//ur existing code to instantiate new thread.
}

I've a problem when I use the Sleep?

why in my code, the TextView does not take except the last count.
the result just is: counter= 4
int i =0;
while (i< 5) {
try {
Thread.sleep((i*1000));
mText.setText("counter"+ i);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// mText does not show
mText.setText("counter= "+ i);
i = i +1;
}
You are blocking the UI thread when your app sleeps, so the screen is not redrawn, hence you don't see the text changes until your loop ends.
The UI thread
When an application is launched, the system creates a thread called
"main" for the application. The main thread, also called the UI
thread, is very important because it is in charge of dispatching the
events to the appropriate widgets, including drawing events. It is
also the thread where your application interacts with running
components of the Android UI toolkit.
For instance, if you touch the a button on screen, the UI thread
dispatches the touch event to the widget, which in turn sets its
pressed state and posts an invalidate request to the event queue. The
UI thread dequeues the request and notifies the widget to redraw
itself.
This single-thread model can yield poor performance unless your
application is implemented properly. Specifically, if everything is
happening in a single thread, performing long operations such as
network access or database queries on the UI thread will block the
whole user interface. No event can be dispatched, including drawing
events, while the long operation is underway. From the user's
perspective, the application appears hung. Even worse, if the UI
thread is blocked for more than a few seconds (about 5 seconds
currently) the user is presented with the infamous "application not
responding" (ANR) dialog.
If you want to see how bad this can look, write a simple application
with a button that invokes Thread.sleep(2000) in its OnClickListener.
The button will remain in its pressed state for about 2 seconds before
going back to its normal state. When this happens, it is very easy for
the user to perceive the application as slow.
To summarize, it's vital to the responsiveness of your application's
UI to keep the UI thread unblocked. If you have long operations to
perform, you should make sure to do them in extra threads (background
or worker threads).
More info:
http://developer.android.com/resources/articles/painless-threading.html
That is the problem. And AsyncTask is (one) solution:
AsyncTask
AsyncTask enables proper and easy use of the UI thread. This class
allows to perform background operations and publish results on the UI
thread without having to manipulate threads and/or handlers.
An asynchronous task is defined by a computation that runs on a
background thread and whose result is published on the UI thread.
http://developer.android.com/reference/android/os/AsyncTask.html
First, it would be a good idea to change the text before sleeping.
Second, if you do this in a separate thread, you have, nevertheless, to manipulate a widget in the ui thread. Try this :
instead of
mText.setText("counter"+ i);
try
runOnUIThread( new Runnable() {
public void run() {
mText.setText("counter"+ i);
}
});
Regards,
Stéphane
"while (i <= 5)" will make it go on till five.
Another solution is to make "i" 1 to start with, instead of 0.
Does this help?
Use a for loop (inside a non-UI thread):
for (int i = 0; i < 5; i++}{
try {
Thread.sleep((i*1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUIThread(new Runnable() {
public void run() {
mText.setText("counter"+ i);
}
});
}
Many answers here gave you all the information you need to achieve what you want but it may be difficult to understand.
I will propose you below a new way to achieve it, maybe easier. But I want to underline that you should understand what people wrote, my previuos post and the one from #LAS_VEGAS at least.
Here is something easy : use a handler.
add a data member like
Handler handler = new Handler();
then on click :
for (int i = 0; i < 5; i++}{
handler.postDelayed( new Runnable() {
public void run() {
mText.setText("counter"+ i);
}
}, i * 1000 );
}
I don't have access to my very own computer right now and fear this may not compile due to a non final variable used inside a annonymous inner class. So you could also try to build a named inner class like this in your main java class :
public class ButtonTimerThread implements Runnable
{
privqte int i =0;
public ButtonTimerThread( int i)
{
this.i = i;
}//cons
public void run()
{
mText.setText("counter"+ i);
}//met
}//class
qnd then you click listener method would look like :
for (int i = 0; i < 5; i++}{
handler.postDelayed( new ButtonTimerThread( i ), i * 1000 );
}
As your handler will be created by the UI thread, it will be able to update UI. The handler offers the advantage to have a delay mechanism that doesn't block the UI thread that is reacting to your click action.
I hope this helps,
Stéphane
Generally, good solutions to problems with sleep() involve stopping using sleep(). Blocking the UI thread is always a very bad idea. It makes you application's UI non-responsive.
In your case you want an event to run every second. The correct way to implement that is with a timer.

How to put an app main thread to sleep, to show progress dialog changes?

I have an app and want to put the main thread to sleep for 1500ms, so I can show a ProgressDialog, but I don't know how to do it. It's possible to stop an app main thread? I can achieve the same goal using another thread right?
Stopping the main thread is usually a bad idea as it would also stop all UI interaction processing.
Try making the progress dialog modal. This will prevent the user from doing anything on your UI until the dialog is gone. I think this will achieve what you want to do and is compatible with how Android works
not a good idea to do this, but if you have to use this
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
//handle
}
Don't stop main UI thread! It will freeze UI. I can imagine that you show progress dialog during some background operation. Once this operation is complete just post something to update UI via handler.
The point of progress dialog is to interact with user while something long is executing. Otherwise you would not even need background operation and progress dialog. You would just do you operation in main UI thread and wait for UI to unfreeze.
What you're asking for should be unnecessary and as Carsten said, is a bad idea. It's a cardinal rule that you both never interrupt the UI thread and also only update elements of the UI on that thread. While a Dialog and any of it's subclasses are shown, nothing in the background will receive any input, so while it's up... though the main thread is running, nothing should be happening besides what is going on in the Dialog.
What you're probably looking to do is use something like an AsyncTask() to show your ProgressDialog, do some work, then dismiss it when that work is done.
To do something like this, you'll want to use "Runnables" along with a "Handler." As others mentioned, you don't want to stop the main UI thread. Since there is only one, you won't be showing ANY updates if you make it sleep or wait. See a small sample below of running code on another thread.
The main thing to take out of this is that sleeping the main thread means stopping any and all visual updates.
// Class Variables
private Handler mHandler;
#Override
public void onCreate(){
// Create a Handler Object
// In Layman's terms, Handlers can run processes off the main
// User interface thread.
mHandler = new Handler();
// Post a "Runnable" after a delay in milliseconds
// On a separate thread, the progressDialog_Runnable
// will call the function "createProgressDialog"
mHandler.postDelayed(progressDialog_Runnable, 250);
}
// Runnables (Process to run on separate thread)
private Runnable progressDialog_Runnable;
{
progressDialog_Runnable = new Runnable(){
#Override
public void run() {
createProgressDialog();
}
};
}
// Method you create to make the progress dialog
private void createProgressDialog(){
//... Run this code on a separate thread via Runnable
}
Sleep 10s on a thread in Kotlin
try {
Thread.sleep(10000)
} catch (e: InterruptedException) {
//handle
}

Updating Swing component from another thread with invokeLater or SwingWorker

I'm developing a small app, which would have Swing GUI. App is doing IO task in another thread, when that thread finishes GUI should be updated acordingly to reflect thread's operation result. Class running in a (worker, non-GUI) has object passed to it in contructor which would be used for updating GUI, so I don't need to put GUI stuff in a non-GUI class, but rather pass object for updating GUI to that class.
As I understand form reading here, (thread/swing) safe options for updating (changing) Swing GUI would be to use javax.swing.SwingUtilities.invokeLater(), javax.swing.SwingUtilities.invokeLaterWait() and/or javax.swing.SwingWorker() which basically are doing the same thing.
This all threading issue with Swing is a little confusing for me, and yet I need to use threads to do anything meaningful in GUI apps and not hung GUI while processing in EDT, so what interests me for now is this:
Are invokeLater and invokeLaterWait like sending message to EDT and waiting for it do it when it finishes processing messages that were before that call?
is it correct from Swing thread safety aspect, to do something like this:
interface IUPDATEGUI {
public void update();
}
// in EDT/where I can access components directly
class UpdateJList implements IUPDATEGUI {
public void update() {
// update JList...
someJList.revalidate();
someJList.repain();
}
}
class FileOperations implements Runnable {
private IUPDATEGUI upObj;
List<File> result = new ArrayList<File>; // upObject is accessing this
public void FileOperations(IUPDATEGUI upObj) {
this.upObj = upObj;
}
private void someIOTask() {
// ...
// IO processing finished, result is in "result"
}
public void run() {
someIOTask();
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
upObj.update(); // access result and update JList
}
}; );
}
}
In case this isn't correct then how should this be done?
If I could, I would prefer to use invokeLater instead of SwingWorker if possible, because I wouldn't need to change my whole class and it's somehow more neat/distinct me (like sending a message in Win32 apps).
Thanks in advance.
Using invokeLater() and invokeAndWait() passes the Runnable parameter into the queue awaiting execution in the EDT. So calling invokeLater() will cause the Runnable to execute in the EDT when the EDT is able to process the request. invokeAndWait() simply waits (in the calling thread) until this execution takes place.
Using SwingWorker is ideal if you want to do background tasks that notify the EDT either at the end of execution or in intermediate states. An example would be to pass the current progress of a process to a JProgressBar.
For your example it seems that SwingWorker is a better choice but if you don't want to change your code too much then calling invokeLater() when the process is done will be just fine.
I'd recommend not using the invokeAndWait until java 7. I found a spurious wake-up on this method that can cause really painful bugs. For me it led to some really rare and hard to debug null pointer exceptions.
http://bugs.sun.com/view_bug.do?bug_id=6852111
It's fixed as of java 7 b77.
invokeLater is fine. This puts the call into the AWT event queue, so that it will get executed in the EDT in due course. Your program will continue running, and does not wait for your callable to get called.

Categories