QT Jambi - QLCDNumber updated in real-time - java

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 :).

Related

JFrame gets locked completely while method is running

I have a GUI(JFrame), with two Buttons and 1 Panel to show the result. One Button is to start the algorithm, one for stopping it. By pressing start, a method is called and it starts running. The runtime of this method varies from couple of seconds to 2-3 minutes, depending on the input.
The problem I have hereby is, by pressing the start-button, the GUI gets completely locked. I cannot press any button till the algorithm terminates. It would be great to be able to stop the algorithm and to visualize parts of the solution after a certain amound of time.
I checked every single line of the Frame, there is nothing that disables it.
//If needed I can provide code, but its pretty long and just some hints and reasons for the problem would be great and I try to fix it by myself.
thanks in advance.
Don't put long-running tasks on the EDT, or the Event Dispatching Thread. Use threading or a SwingWorker instead. Hopefully that's enough google keywords to get you started. :)
It sounds like your algorithm is running in the same thread as the UI components. You probably want to read up on Concurrency and Concurrency in Swing to better understand how to create threads, monitor execution, integrating these concepts with a Swing-based user interface, and so forth. At a very high level, you are going to need to somehow spawn a new thread when your algorithm starts and observe it for intermediate state changes to update the UI. You only want user interface related code running in the event dispatch thread.

Java: How to interrupt a program partway through execution with a mouseclick

How would one go about implementing a mouselistener (or some other way, doesn't matter) that will handle a mouse click event at ANY part of the program? Preferably returning to the line it left off at when the click event handler method completes.
I am using swing. The 'context' is a GUI that constantly updates, but must respond to a mouse click from the user at any time with no delay. Indeed I do have experience with events, using and overwriting their handlers etc., not too in-depth I suppose but what i do know has been sufficient in anything until now.
I could not understand your first para, so my answer goes for your second para, if I understood that correctly. ;)
Swing follows single thread model. So, you should be updating the UI from Event Dispatch Thread (EDT). This thread is responsible for delivering the events to your code too, hence the name. If you are continuously updating an UI in a loop then that is going to keep the EDT busy and blocked. The end effect will be an UI which does not respond to user events. This because the events are getting queued and EDT can pick them and deliver them to your code when it becomes free.
Games typically encounter this kind of scenario. You might have noticed that games typically have one fixed rate of refresh which they call FPS (Frames Per Second). Typically maintaining 60 FPS is good enough. That is, you need to draw your UI 50 times per second, but right now it seems that your render loop (which updates the UI) is running continuously.
You need to have separate thread continuously running which is responsible for drawing the UI. This should draw into a buffer (Image). And then invoke repaint() on the UI element to be updated. That UI element's paintComponent() needs to overridden, so that it can copy the image in Image buffer and paint that on the graphics context.
Now comes the real trick. The loop which calls repaint() must do some arithmetic to make sure it does not go beyond drawing 60 times, i.e. looping 60 times, per second. If and when it does then it must call Thread.sleep(sleepTime), where sleepTime is the number of milliseconds left in a second after looping 60 times. It might happen sometime that your loop may take more than a second to complete 60 iterations, then don't just go ahead for next iteration, but call Thread.yield(). This will give other threads a chance to use the CPU, e.g. maybe your EDT. To make the matter more complicated, do not keep yielding always, so might want to put some logic to make sure that yield for only x consecutive times. This last scenario should be very rare, if at all. This scenario means the system is under heavy load.
Remember, repaint() is thread safe and allowed to be called from any thread. It schedules a paint() call on EDT. So, calling repaint() does not guarantee a paint. So, you may want to experiment with different values of FPS to find the one which suites you.
By the way, the trick of rendering to an in-memory Image is technically called Double buffer. This gives us the ability to render nice smooth animations.
Further reading:-
LANSim - Wrote this code a long time back. You can use this code as an example.
http://java.sun.com/docs/books/performance/1st_edition/html/JPSwingThreads.fm.html
Killer Game Programming in Java - This book is on this subject.
Have you looked at SwingWorker? It's a simple framework that lets you run computations in the background and periodically publish updates to the GUI thread.

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 to make an animation with Swing?

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.

Gameloop for j2me "turn-based" game

Edit: This makes alot more sense to me now that i've taken a step away from the code, thanks for the help.
Just found stack overflow the other day through Coding Horror and it looks awesome. Figure that i'd ask the community about a problem i'm currently trying to work out.
I'm developing a roguelike sortof game using j2me for midp 2.0 phones. The project is still in the basic stages of development as I figure out how it's going to work. The part i'm currently stuck on has to do with threading.
The game has a custom HaxCanvas class which extends GameCanvas and Implements runnable. It's run method calls repaint() and then sleeps for 50 ms, resulting in a frame rate of 20 FPS. This allows me to write the rest of the game without having to put repaint everywhere and should make animations and effects easier to do later on. (at least in theory).
The flow of the game is controlled by a GameManager class, which loops through all the NPC's on the map, taking their turns, until it's the player's turn. At this point I need to get input to allow the player to move around and/or attack things. I originally was calling gameManager.runUntilHeroTurn() in the keyPressed method of my HaxCanvas. However after reading up on j2me system threads I realized that putting a method with the potential to run for a while in a callback is a bad idea. However I must used keyPressed to do input handeling, since i need access to the number keys, and getKeyStates() does not support this.
Sofar my attempts to put my gameloop in it's own thread have resulted in disaster. A strange "uncaught ArrayIndexOutOfBoundsException" with no stack trace shows up after the game has run for several turns .
So i suppose my question is this:
For a "turn based" game in j2me, what's the best way to implement the game loop, allowing for input handeling only when it's the player's turn?
Although not j2me specifically you should capture user input, the general strategy is to queue the input it until its time to process the input.
input ---> queue <---> Manager(loop)
This way you can even script input for debug purposes.
So you don't need a new thread. Each time the user presses key you store them in a buffer, and then process the contents of the buffer when necessary. If the player buffer has no input, the manager should skip all gameplay, do animations and then start over (since the game is not an action game).
I would avoid threading for the game logic as J2ME threading, depending on manufacturer of course, does not do a great job of sharing the limited resources. You will often see pauses while a thread does heavy processing. I would only recommend threads for loading or network connectivity features as in this case you will just be giving the user basic "Loading..." feedback.
To handle this, I would not have sub-loops to update each of the AI in one frame. I would do something like following in the run function:
public void run() {
while(true) {
// Update the Game
if(gameManager.isUsersTurn()) {
// Collect User Input
// Process User Input
// Update User's State
}
else {
// Update the active NPC based on their current state
gameManager.updateCurrentNPC();
}
// Do your drawing
}
}
You want to avoid having everything updated in one frame as 1) the updating might be slow, resulting in no immediate visual feedback for the user 2) you can't animate each individual NPC as they make their action. With this setup you could have NPC states, NPC_DECIDE_MOVE and NPC_ANIMATING, that would allow you further control of what the NPC is doing. NPC_ANIMATING would basically put the game in a waiting state for the animation to take place, avoiding any further processing until the animation is complete. Then it could move on to the next NPC's turn.
Also, I would just have a gameManager.update() and gameManager.paint(g) (paint would be called from paint) that would handle everything and keep the run method thin.
Finally, did you look into flushGraphics()? With the GameCanvas you usually create a Graphics object, draw everything to that and then call flushGraphics(), then wait. The method you mention is the way of tackling it for the Canvas class. Just thought I would mention this and post a link:
Game Canvas Basics

Categories

Resources