Im trying to display series of photos on one page with time interval. In countinuos while loop i got:
while(true){
if (zmienna == fa.length) zmienna = 0;
Image obrazek = new Image("",pliki[zmienna]);
layout.replaceComponent(staryObrazek, obrazek);
obrazek.requestRepaint();
staryObrazek = obrazek;
zmienna++;
try {
Thread.sleep(2000) ;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
It showing only waiting icon, dispaying mwthod works fine without loop. Do anyone has an idea how I should fic this issue?
In all modern UI systems you will have to not suspend the main thread, but use a background thread to update the UI. Otherwise you block the whole UI.
In Vaadin 7 you can enable server push and then use a background thread to change the image every 2 seconds.
Enabling push is described in the book of vaadin https://vaadin.com/de/book/vaadin7/-/page/advanced.push.html
Your code could look like this:
public class PushyUI extends UI {
#Override
protected void init(VaadinRequest request) {
// Set first component/image
setContent(chart);
// Start the update thread
new ImgUpdThread().start();
}
class ImgUpdThread extends Thread {
#Override
public void run()
{
// Update the data for a while
while (count < 100) {
Thread.sleep(1000);
access(new Runnable() {
#Override
public void run() {
//update the UI as in your code above
}
});
}
}
It is important to use the access(...) method to sync access to the UI elements.
Related
I wanted to mock location of a marker on map. I have list of LatLng values store in ArrayList. I use this value to update on map every second. I need this function to works in AsyncTask so that my UI thread will still responsive.
Initially, I tried using Thread.sleep() but made application not responsive.
protected String doInBackground(Void... voids) {
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
for (int i = 0; i < waypoint.size(); i++) {
marker = googleMap.addMarker(new MarkerOptions().position(waypoint.get(0)));
marker.setPosition(waypoint.get(i));
try {
Thread.sleep(1000); // Thread sleep made application not responsive.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}, 500);
return null;
}
I also tried using .postDelayed but the integer i needs to get declared final which is a problem because I need the integer to change value.
protected String doInBackground(Void... voids) {
for (int i = 0; i < waypoint.size(); i++) {
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
marker = googleMap.addMarker(new MarkerOptions().position(waypoint.get(0)));
marker.setPosition(waypoint.get(i)); // Integer i needs to declare final.
}
}, 1000);
}
return null;
}
Is there any way to do this? Thank you.
The Thread.sleep() approach is OK if you can spare a worker thread. The problem in your code is that the thread you are pausing is the UI Thread, that's why your application freezes. You have to understand that what your doing there is just publishing a runnable to the UI Thread using the Handler construct, nothing more.
In your second approach, you can dump the Handler part and use publishProgress (called from the background) after you override onProgressUpdate (delivered in UI thread) in your AsyncTask based class. It does effectively the same but with less boilerplate. Take a look at https://developer.android.com/reference/android/os/AsyncTask for details.
Finally, to circumvent the final requirement in anonymous classes, you can declare a final array of one element and use position 0 to read/write the value. Hopefully, you won't need to do this too often.
The fastest (but not the most correct when working with MultiThreading) way is:
protected String doInBackground(Void... voids) {
for (final TYPE_OF_WAYPOINT cWaypoint : waypoint) {
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
marker = googleMap.addMarker(new MarkerOptions().position(waypoint.get(0)));
marker.setPosition(cWaypoint);
}
}, 1000);
}
return null;
}
I don't know what was the Type of "waypoint" List, so I wrote "TYPE_OF_WAYPOINTS" as placeholder.
#emandt answer does not work but the idea he gave could work. So I tried and it is working flawlessly with some modified from his answer:
protected String doInBackground(Void... voids) {
for (final TYPE_OF_WAYPOINT cWaypoint : waypoint) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
marker = googleMap.addMarker(new MarkerOptions().position(waypoint.get(0)));
marker.setPosition(cWaypoint);
}
});
try {
Thread.sleep(1000);
} catch (Exception e) {
// catch exception here
}
}
return null;
}
Firstly, I have change the .postDelayed to .post. Then, to delay the operation by one second, I have added Thread.sleep(1000) inside for (...) but outside new Handler(Looper.getMainLooper()).post(...));.
Now, the application could do the process in the background with user still be able to interact with the UI. Thanks.
I am making a program in which I am supposed to make visibility of labels false after, say, 1 sec intervals
The program is pretty long and complex to quote so I am explaining it. I have an array of labels and each time a label is setVisible(false), slp() method is executed.
public void slp()
{
try{
Thread.sleep(1000);
}
catch(Exception e)
{
System.out.println(e);
}
}
But I am facing a problem. The method just increases the time of execution of thread and all the labels become invisible together at last. I need animation effect, and that is not coming.
What would be a good solution to my problem? Can a timer serve me?
First, your method slp should probably take a JLabel as argument, so you can modify the visibility of a specific label. Otherwise, the method would not know which label to hide.
Second, in order not to block the main thread (or whatever thread that class slp()), the Thread.sleep(1000) should be run in its own thread. That's why the code below uses new Thread(....).start(); to create a new thread that will do the actual work.
Third, as the waiting now is in a separate thread, changing the labels visibility must be done again on the Swing Events thread. For this, we use SwingUtilities.invokeLater() where we then set the label's visibility.
All together, the code could look like this:
public void slp(JLabel label) {
new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
label.setVisible(false);
}
});
}
}).start();
}
The code could be further "cleaned up" by using lambda-expressions as available since Java 8:
public void slp(JLabel label) {
new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
SwingUtilities.invokeLater(() -> label.setVisible(false));
}).start();
}
Hi i got following problem...
I have main jframe started like this:
public static void main (String args[]){
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Form3 myF=new Form3();
}
});
};
in the jframe i have Jpanels. On jpanel i want to start 2nd thread.
I tried it like this:
try {
while (DBAccess.haveResult("ASS"+harnessId)==null&&cancelCycle == 0) {
thread1.sleep(3*1000);
System.out.println("+++++++++");
System.out.println(DBAccess.haveResult("ASS"+harnessId));
res = DBAccess.haveResult("ASS"+harnessId);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
but I am unable to stop that thread and cant even cancel it, because main window stops reacting
to clarify my problem:
i have "Test" button on JPanel, which is starting test process. Test process consists of loop whiuch is repeating every 3 seconds, this loop checks database status. Problem is I am unable to stop this loop until the status appears in db (while condition), because window is busy after i click on "test". Even implementing runnable and putting test method into "run()" doesnt worked.
testbutton source code:
if (e.getActionCommand().equals("Test")){
run();}
run method:
#Override
public final void run() {
test();
}
test method:
Map result_row = DBAccess.addRow("ASS"+harnessId,htOperList.get(seqNumber-1).getNametestprogram(),"",null);
if(result_row.containsKey("ADDROW")){System.out.println("Record inserted" );}
Database db = null;
Map res = null;
try {
while (DBAccess.haveResult("ASS"+harnessId)==null&&cancelCycle == 0) {
thread1.sleep(3*1000);
System.out.println(DBAccess.haveResult("ASS"+harnessId));
res = DBAccess.haveResult("ASS"+harnessId);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
You are blocking the event dispatch thread. Use a SwingWorker for heavy tasks. Put the main DB operation in doInBackround(), and use publish() for the interim results.
If you need to stop it before doInBackround() completes, you can use cancel(). See here for notes about that.
I've created my first live wallpaper implementing drawing in a separate thread. So now I have a WallpaperService and my WallpaperPainter who does the job. The problem is that I getting a IllegalArgumentException in unlockCanvasAndPost method on some of devices (Samsung Note is the one). I've read all recomendations I could find but couldn't fix that bug. Seems like the unlockCanvasAndPost is called when surface is destroyed so canvas is invalid. Here is the essential parts of code:
In wallpaper service:
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
super.onSurfaceChanged(holder, format, width, height);
painting.setSurfaceSize(width, height);
}
#Override
public void onSurfaceCreated(SurfaceHolder holder) {
super.onSurfaceCreated(holder);
painting.start();
}
#Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
painting.stopPainting();
while (retry) {
try {
painting.join();
retry = false;
} catch (InterruptedException e) { }
}
super.onSurfaceDestroyed(holder);
}
In the painting thread:
public void stopPainting() {
this.run = false;
synchronized(this) {
this.notify();
}
}
public void run() {
this.run = true;
Canvas c = null;
while (run) {
try {
synchronized (this) {
Thread.sleep(50);
c = this.surfaceHolder.lockCanvas();
doDraw(c);
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (c != null) {
this.surfaceHolder.unlockCanvasAndPost(c); // << -- HERE IS THE PROBLEM
}
}
// if pause...
synchronized (this) {
if (wait) {
try {
wait();
} catch (Exception e) { }
}
}
}
}
Can anyone give me any clue what I'm doing wrong? I'm new both for Java and Android.
If error is: UnlockAndPost Failed, it means it unlocked no buffer.
After this.surfaceHolder.unlockCanvasAndPost(c);
you can append
this.surfaceHolder.lockCanvas();
(sorry for my poor English proficiency)
When you open the preview of wallpaper, creates the object WallpaperService and further creates an instance of Engine. Then the stream starts drawing wallpaper.
Then, when you click "Set wallpaper" - a new instance of WallpaperService is not created. But he call the onCreateEngine() method, which returns another (second) instance of Engine. Which also runs its own thread.
Now you have two competing thread!!! So they lead to an exception being thrown.
All you need to do to fix the bug - is to write a correct method onCreateEngine().
replace this:
#Override
public Engine onCreateEngine() {
return new SampleEngine();
}
to this:
private SampleEngine engine;
#Override
public Engine onCreateEngine() {
if (engine!=null) {
engine.painting.stopPainting();
engine = null;
}
engine = new SampleEngine();
return engine;
}
I don't see a definitive problem but here are some thoughts.
There is a chance that you unlock a canvas that has not been locked. I would set c = null; at the top of your while loop otherwise the previous value of c would be unlocked the next time through the loop.
while (run) {
Canvas c = null;
...
Your run field should be marked as volatile because it is accessed by multiple threads.
Never call Thread.sleep(...) inside of a synchronized block. That's a very bad practice since it blocks other threads unnecessarily.
Make sure you at least log your exceptions. Be extremely careful about catch (Exception e) {}. All that does is mask your problems.
There isn't much point in doing the join() inside a while loop. If your thread gets interrupted you should interrupt the painting thread and quit.
Since you are both sleeping and waiting, it would make more sense to remove the sleep and do something like:
try {
synchronized (this) {
if (wait) {
wait();
else {
wait(50);
}
}
} catch (Exception e) {
e.printStackTrace();
}
I had the same problem with my live wallpaper. On a Nexus 5 emulator it runs fine, but when I run it on a Nexus 10 emulator it crashes the moment the app loads.
I found out that the problem was because the default Skin for the emulator has the wrong resolution. After I changed the Skin to "No Skin" then I don't get the crash anymore.
For more information on how to fix the Skin with wrong resolution, please see:
Android Studio - Tablet emulator not showing correct resolution
Unfortunately I have a pretty bad understanding of how to properly set up threading. I know there is a bunch of info on this both here on SO.SE and on other sites but I can't seem to relate what I read correctly to what I'm doing.
My problem is that I have a method that takes two parameters where one is divided by the other. The quotient (result) is used to fill up a visual progress bar. When the quotient gets to 1, (readBytes/contentLength == 1), I want some thread (I guess) to wait for a given time before the progress bar is removed from the layout. I know all the code needed to set the value to the progress bar and how to remove it from the view, my question is how do I make it wait for, say, 2000 ms before the action is triggered to remove the component?
This is probably basic threading knowledge but I'm having huge problems with it.
So far I've tried these two approaches:
#Override
public void updateProgress(long readBytes, long contentLength) {
this.contentLength = contentLength;
if(readBytes != 0 && contentLength != 0 && fileListItem != null) {
fileListItem.getProgressIndicator().setValue(readBytes/contentLength);
synchronized (this) {
while(readBytes/contentLength != 1) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
};
fileListItem.removeProgressIndicator();
}
}
}
if(!itemIsAdded) {
checkFileCompatibility(contentLength);
}
}
AND
#Override
public void updateProgress(long readBytes, long contentLength) {
this.contentLength = contentLength;
if(readBytes != 0 && contentLength != 0 && fileListItem != null) {
if(readBytes/contentLength == 1) {
Thread t = new Thread();
t.start();
try {
t.wait(2000);
fileListItem.removeProgressIndicator();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t.interrupt();
} else {
fileListItem.getProgressIndicator().setValue(readBytes/contentLength);
}
}
if(!itemIsAdded) {
checkFileCompatibility(contentLength);
}
}
With no success. In the first example the main thread seems to be the one waiting and nothing happens. And in the second example I get an exception on the t.wait(2000);. I'm at a loss of how I should do..
EDIT: With the input from Bohemian I got it working.
#Override
public void updateProgress(final long readBytes, final long contentLength) {
this.contentLength = contentLength;
if(readBytes != 0 && contentLength != 0 && fileListItem != null) {
if(!threadIsRunning) {
new Thread(new Runnable() {
#Override
public void run() {
threadIsRunning = true;
while(!fileIsAdded) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
LOGGER.error(e.getMessage());
break;
}
}
fileListItem.removeProgressIndicator();
threadIsRunning = false;
}
}).start();
}
fileListItem.getProgressIndicator().setValue(readBytes/contentLength);
if(readBytes == contentLength)
fileIsAdded = true;
}
if(!itemIsAdded) {
checkFileCompatibility(contentLength);
}
}
It still needs some tidying up but the basics are now working!
In all probability SwingWorker is the right tool for your task. There is a full code sample in the Javadoc. Notice the method setProgress -- that's ideal to update your progress bar.
If all you need is really just a fixed 2 second delay for clearing the progress bar, then you want to use a Swing Timer. It doesn't even involve multithreading, you just write a callback handler that will be executed after the specified delay.
I wouldn't have the main thread wait. It's bad practice because it isn't scalable and makes your GUI jittery.
Instead, I would pass a timeout value and a couple of callbacks to the worker thread to execute when it exceeds its timeout/completes its work. That way the main thread is free to go back to doing whatever it wants to.
Just for illustration purposes, your "completion" callback might look like:
new Runnable() {
public void run() {
// code that hides the progress bar
}
}
Your "timeout" callback might look like:
new Runnable() {
public void run() {
// code that displays an error message
}
}
By the way, to get a thread to do something, you also pass it a Runnable:
new Thread(new Runnable() {
public void run() {
// code that runs when your thread starts
}
}).start();
I think what you really need is
Thread.sleep(2000);
instead of wait. While wait can be used for sleeping, its primary function is for inter-thread signaling and requires a lock on the object being waited on, which you have not acquired, hence the exception.
Edit: Upon further inspection I notice that you are not doing things correctly. You are just creating a thread with no associated run method:
Thread t = new Thread();
t.start();
Hence your thread is not executing anything.
I suggest reading a Java threading tutorial on how to set up threads correctly: http://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html