How to make an animation with Swing? - java

I am making a JApplet and got stuck with a animation problem.
Here is my code :
this.sprite.setBounds(0,0,20,17);
this.sprite.setIcon(this.rangerDown);
for(int i = 0; i< 16;i++)
{
this.sprite.repaint();
this.sprite.setLocation(this.sprite.getX(), this.sprite.getY()+10);
try{
Thread.currentThread().sleep(100);
}catch(InterruptedException e){
}
}
With this, there is no animation : nothing happens during the loop, the repaint() method seems to only act once the sprite stopped moving.
I would like to use only Swing for this, any ideas of how to proceed ?
Thanks for reading.

You should use a javax.swing.Timer to perform the animation rather than Thread sleeps. Here is a good link to get you going: http://java.sun.com/docs/books/tutorial/uiswing/misc/timer.html
Also I highly recommend buying the book Filthy Rich Clients -- if you go to the website you can also download all the example code for free. For example, Chapter 12: Animation Fundamentals has some great examples, such as MovingButton that demonstrates the Timer usage.

You left out the code surrounding your code, that makes it a little harder to help you.
You most likely have a problem with thread handling. There's a Swing worker thread responsible for displaying your stuff; if you're sleeping inside that thread it's not able to do its work. If you're changing the image from outside this thread, then it may not be picking up the change because you're not properly synchronizing with the Swing thread.
You need to use something like SwingUtilities.invokeLater(Runnable r) to accomplish this, where your image-changing code would be in r's run() method. If you Google for "invokeLater" and Swing, chances are you'll find examples.

Related

JavaFX - update label values from other thread

Helo guys!
I am new to JavaFX. I am writing really small application which simulates working of printer. Simulation is running on special thread called PrintingProcess (this process is doing only one thing - waits given time and then increment counter). I need to send this value to window, where labels should show how many pages was "printed". Is any way to do it? So far I wrote small singleton class to hold value.
[edit] I solved it using tasks :) thanks for help
You should use the Task.updateProgress method. Call it to specify the current percentage of pages printed. Override Task.call to perform the action which needs to run in another thread. This method should never manipulate a JavaFX component. You can then oerride methods such as Task.succeeded to implement the behaviour of your UI when the print job is over. Look at the doc of this class to fully take advantage of it.
Platform.runLater(new Runnable() {
#Override public void run() {
textLabel.setText(yourValue);
}
});
The example above is quite simple. You ask JavaFX a runnable as soon as it can. I don't know how that works exactly but that's the way to change UI components from a non-JavaFX thread.
You could pass textLabel variable to any thread with a custom class or a new anonymous thread.
EDIT:
I find Dici's answer more appropriate for your application. I wouldn't recommend putting this code in any loop incase you may still use this.

Does suspending thread make any changes?

I have a simple question
does it make any difference to try suspending a thread(in my situation)?
my thread is just an image rotator (my minSDK is 8 so must use matrix, not animation)
i have just asked a question about how to suspend a thread. everyone offered using:
while(isPaused){
try {Thread.sleep(25);}catch(...){...}
}
and my code is like this :
while(true){
//rotate image 15 deg
try {Thread.sleep(25);}catch(...){...}
}
they offer to use the first while inside the while(true)
does it make much difference ?
(I don't have to stop the thread. I can just make the rotating image invisible)
Simpler :
Does it make difference to use this to pause a thread :
while(true){
while(isPaused){
try {Thread.sleep(25);}catch(...){...}
}
//rotate image 15 deg
try {Thread.sleep(25);}catch(...){...}
}
or there isn't any problem leaving the code to rotate an invisible image ?
Edit: considering this is for a custom loading indicator, please don't use a thread. That is overkill for such a simple thing. Have a look at this answer on how to create custom loading indicators using animations.
https://stackoverflow.com/a/8129496/2910492
This has entirely to do with your application. Some more information would be useful, but in general, it seems unnatural to have an image rotating while things are supposed to be paused. Even if the image is invisible, it would (presumably) come back in a different orientation than it was when paused.
Also, the computer's resources must be consumed to continue rotating the image, which is probably not desirable. So I'd revise your code to keep things from executing while paused as such:
while(true){
if(!isPaused){
//rotation code
}
try {Thread.sleep(25);}catch(...){...}
}
Doing things this way eliminates some re-use of code. When you have a way to eliminate code and not repeat yourself, it is almost always a good idea to employ it. Repeated code means repeated errors and makes more work for you when you need to change something. If you have to copy and paste something, stop and do some soul-searching: there is most likely a better way.
You should use the "condition" instead of "true" in your while loop. That condition should be useful to complete the working of the thread.
For e.g. you may not want to make the thread orphan and keep on running even if application gets ended. So in onDestroy you can make that conditional flag false and your while loop gets failed hence thread completes it's task.

QT Jambi - QLCDNumber updated in real-time

In my university, we are working with interfaces, using QT Jambi (Java) with the Eclipse Integration.
I would like to improve my design of my Elevator interface.
The main problem is that I would like to update the QLCDNumber with the floor in real-time.
What I do to simulate the elevator working, is to do a Thread.sleep(1000) between 2 floors, so that way, my QLCDNumber will display "an animation" saying "1...2...3...4". The problem is that the QLCDNumber only displays 1 and 4, no animation.
So, for example (resumed), the code I made is this one:
private void simulate(int floor){
while(actualFloor < floor){
try{
Thread.sleep(1000);
}catch(InterruptedException e){};
actualFloor++;
ui.LCDfloor.display(actualFloor);
}
}
Why this code only shows the 1st floor and the last one?
Sorry if you didn't understand what I wanted, my English is improving every day :)
Thank you in advance.
*Please note that LCDFloor is the name of the QLCDNumber widget
It looks like you have two problems:
(I assume) You're calling Thread.sleep() on the GUI thread. In other words, when you call simulate, you're doing so on the same thread as the rest of the gui operations. This causes the entire gui to pause.
You've never given Qt the chance to actually update the UI. When you call ui.LCDfloor.display(actualFloor), the a paint event is queued so that the UI can be updated, but rather than giving the UI a chance to actually execute the paint event, you continue with your loop which prevents the UI from ever being updated until after your simulation is finished.
You have two basic fixes:
Don't sleep, it's poor design. Instead, use timer's and signals to simulate the changes.
Force events to be processed using processEvents.
Also keep in mind that you can't update a GUI element from a non gui thread. And as this is homework, I'll leave the rest to you :).

Display objects in JFrame one at a time, or frame by frame

I've made a program in Java (eclipse) that displays squares and triangles on a grid using JFrame. The program determines where the objects go in a "for loop". I would like to have the objects appear one at a time (in a frame by frame type of approach). It seems like a "sleep loop" should be used to solve this problem. However I feel that a lack of understanding of java.awt*; is causing me problems. I adding the following to my "for loop"
try
{
Thread.sleep(1000); // do nothing for 1000 miliseconds (1 second)
}
catch(InterruptedException e)
{
e.printStackTrace();
}
The program waits, but draws the objects all at once after it is done sleeping. I have gone through my program and found that this "sleep" command is working to some extent (waiting before processing the next command) I put a println statement within said "for loop" to test it and the program waits one second before printing each println. But I don't know why JFrame draws everything only once at the end. Should I be using something like repaint() every time I want to display a new frame?
MY project structure is 3 classes. Main which simply calls DisplayFrame. DisplayFrame which sets up the Frame. And MyComponent which contains my "for loop" and the "sleep command".
Any help would be appreciated.
There is a tutorial here that uses a Timer to update an image at regular intervals. The example program is an applet, but the principle is the same.
sleep is probably a bad idea. Use a Timer instead:
http://download.oracle.com/javase/6/docs/api/javax/swing/Timer.html
From your description it is a little hard to guess what is going on, but I'm almost sure at least one of two bad things is happening:
you are sleeping in the EDT (Event Dispatch Thread) this locks the complete GUI and might be the reason for you not seeing any updates during sleep.
you are changing swing components from outside the EDT which is a sure way into concurrency hell.
Make sure you follow this approach:
Setup a Time to call you in the desired time intervall ( lets say every 0.1 seconds). In the method that is called manipulate you component/object to reflect the new state and call repaint.
let us know if it works. I'm not exactly sure about the repaint call ... might be wrong ..
Interestingly enough, the Applet Tutorial at the Oracle site has an example of an applet that performs an animation using SwingWorkers and Timers. Perhaps it can be useful to you.
Or you can take control of the rendering of the JFrame using concepts from the gaming world, as explained here

How do I give this CPU-intensive Java application a GUI?

I'm writing a little genetic algorithm in Java, as a school assignment. Up until now I've pretty much stuck to doing console applications. However I think a UI would be really helpful for this program, so I'd like to make one. I'm having trouble figuring out how to reconcile a GUI which is event-driven, and a console application which has a beginning and end.
Ideally I'd like to have a bunch of text boxes for settings, and then a Start button. Once you hit Start, the algorithm would start running and the GUI would update on a set interval with the latest program state. How the heck do I accomplish this without the algorithm freezing the GUI or vice-versa? I don't want either one waiting on the other.
How do I get my main loop to not freeze the GUI while the algorithm is running? I assume they need to be in separate threads, but I've never messed with threads before. That seems too complex for this task, which must be commonplace.
You're on to something with threads. GUI programming mandates threads, in most cases -- luckily, Java's threading API isn't too terrible (Python's is modeled on it, so it's doing something right).
Don't be intimidated by threading, though -- it's intermediate, I'd say, but is something that every programmer should understand.
There's a lot of information out there that would predispose you against threads. GUI applications, however, are one area where they are phenomenally useful. Opponents of threading would lead you to believe that an event-programming model would help you in this case, when really, it will not. The solutions that most who say "threading sucks" propose are often worse than threading itself.
You could try to kludge your solution into a single thread, but it would require your CPU-intensive code to yield to the GUI at a predictable interval. That solution sucks. EDIT: Since others are suggesting that approach, let me elaborate on why it sucks: Unbeknownst to you, something is always being updated in a GUI. When you move a window on top and then back off, the entire region under that window is invalidated and code must execute -- in your process -- to redraw that section. Even if you are updating the GUI very quickly, this provides a negative user experience as simple GUI operations block entirely. Buttons highlight when you mouse over, sometimes. A user right clicks. All of these things require CPU time to implement, and if your solitary thread is chewing away on your GA, they will not happen. GUI code being executed is not only your code.
Here's what appears to be a very useful article on the topic.
Two lessons in the trail on the topic are:
Concurrency
Concurrency in Swing
Sorry - it would seem like background tasks would be an easy and obvious sort of thing. Unfortunately, the Java Swing GUI threading model is a bit complicated. There have been some improvements in this area, but one still has to have some knowledge of threading first.
If you have time, I'd suggest reading the chapter on threading in Filthy Rich Clients - Painless Threading through SwingWorker.
If your impatient, just read the JavaDoc on SwingWorker. If you're really impatient, just copy the meaning of life example from the JavaDoc sample usage.
When I was writing a ray-tracer for one of my computer graphics classes in college, I had a long-running task, and I wanted to update the display periodically as the tracer was drawing. I used two separate threads - one thread sleeps, and updates (say every 500 ms); the other thread does the actual raytracing. The key is to synchronize on a common object - in my case, accessing my image buffer was the point of synchronization (one thread can't make changes to the image buffer without first waiting until the other thread is done reading).
For your GA processing, you might have something like this (pseudocode):
Supposing you have some object, generationHistoryObject, which stores the state that you want to display in your GUI, then:
(in Thread #1:)
Generation newGeneration = doMutationAndTestThisGeneration(lastGeneration);
synchronized (generationHistoryObject) {
generationHistoryObject.updateWithNextGeneration(newGeneration);
}
(in Thread #2:)
while (!programIsDone()) {
synchronized (generationHistoryObject) {
drawGuiForCurrentState(generationHistoryObject);
}
Thread.sleep(500);
}
The idea is that you do the time-consuming work for each generation in isolation, then update the part that the GUI has to access in the synchronized block (making the GUI wait to draw until the update is done).
Your problem with Swing is that it is single threaded (which is a good thing) so you want to get your work out of the Swing thread so your application stays responsive.
The thing you need to do is to convert your core algorithm to a Runnable as it can be handled easily by a SwingWorker and with the newer Executors (see Executors for a lot of preconfigured ones). You can also create investigate how to make a PrintStream to a JTextPanel so you can just use standard println statements to output your current status information.
If you want to add a stop button you need to understand the thread model, so you know how to control it. The Java Tutorial has good material on this as well as Swing programming in general. Strongly recommended.
http://java.sun.com/docs/books/tutorial/uiswing/concurrency/index.html
Since your application has to do with genetic algorithms, you could update the GUI every generation or so. You could accomplish this by implementing a next() method in your algorithm code, and calling it from the GUI. This should be simple enough.
However, if you really don't want the GUI to freeze while waiting for the algorithm, you should go for threads.

Categories

Resources