JFrame gets locked completely while method is running - java

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.

Related

Can I run two EDTs?

This is mostly a theoretical question. The example below is what made me think of it, but it may not be the best example. Please assume that the reason's below are concrete, and can't for the moment be worked around.
The Program I have been running has an optional Debug frame that is created on the program startup, and it made visible by the user pressing buttons/keyboard shortcut.
My issue is that as I have lengthy processes on the EDT, if it is hanging for some reason or fails I'd like to see straight away, and not wait for that thread to end running, to update the Debug Log Frame.
My solution would be to have two separate EDT for two separate GUIs that are updated by a separate thread.
Is this possible, or am I not able to do so? I haven't found any online resourcethat would show me how to. I know that EDTs should be single threaded, but if I keep the threads disentangled, can I have two? Please?
The answer is simple: No you cannot have 2 EDTs, that is not possible.
But you are not stuck with a frozen GUI, you have some options available.
First and foremost, two important rules:
Never do lengthy calculations in the EDT. Ever.
Never manipulate Swing components from outside the EDT. Ever.
Breaking the first rule will result in your GUI being frozen and no events of any sort being processed during that time. This includes updates to the GUI you want to do during the calculations which will not appear until after the calculations are done.
The latter is often ignored which will go by unnoticed most of the time, but it can - and will - bite you in the ass and then most of the time it is a huge pita to go back and fix it. So do it the correct way from the start. What can happen? Components can suddenly display in a broken state, they may appear white, or the whole application can freeze because there is a deadlock between the EDT and your other threads (been there, done that). Adhere to the Oracle Swing Threading Policy!
So, how to avoid doing lengthy calculations on the EDT after for example the user pressed a button? Options:
use a SwingWorker. Advantage: Has a done() method you can use which is automatically executed in the EDT once the worker is done. Also implements the Future interface and can therefore be used to return a result.
you can just create your own Runnable and do the calculations in there.
use any other way Java provides for parallel execution.
Ok, and how to avoid ever manipulating GUI from outside the EDT?
call SwingUtilities.invokeLater() and execute Swing manipulations in there.
use the SwingWorkers done() method as described above.
If you follow these two rules, your Swing GUI will be in a much better shape and you can focus more on your application development rather than Swing issues.

Update a JLabel from another thread without having to separate all my processes on threads?

I'm developing a big project on Java Swing. It has a database connection, external devices managing and sd-cards processing.
I currently have a lot of heavy processes that run on the EDT thread, and making separated threads for all of them is a long long task that I'm trying to escape... Besides, It would probably introduce a lot of concurrency problems that I am not willing to handle.
The thing is that I want to introduce a loading JLabel with a loading gif while the long busy tasks are being processed. It is also important to highlight that I want my whole swing interface to be blocked while the long tasks are being done, just like it happens now, EXCEPT for the loading label.
Is there a way to actualize that label from another thread?
If you care about creating a good user experience, there really is no escaping using SwingWorker or similar, to offload work form the event dispatcher thread (EDT). If you need to really need to "block" the UI, you should use a JDialog with a progress bar or similar.
The short answer to your question is no. The Jlabel must be instantiated and added from the EDT.
However, you should be able to add the JLabel, you just have to make sure you do it before the long-running blocking tasks starts. Then remove it after it is done.
Anyway, this is a hack, and a lazy workaround for doing the right thing, and is not recommended. You might experience that you spend more time working around the issue and pulling your hair, than just do it properly with SwingWorkers.

How to write event buffer for Java Swing MouseEvent?

I have been trying to find a solution to this question for a while. What is the best practice for writing a swing event buffer? The idea is when triggering an action from a mouse gesture, such as 'mouseMoved', as the events may be fired many times, I only want to trigger the last call - for example,
if the mouse was clicked five times, while the first click listener is being executed, and four are queued, the next call will be the fifth one - all previous ones will be skipped.
It seems that I should be using the Executor class, as it can remove unsubmitted tasks, but I am still not quite sure. All help is appreciated!
user1291492 is right, this shouldn't happen at all. You should never run any code that could take longer than a couple of milliseconds to complete in an event handler. The SwingWorker documentation contains examples and explanations on how to do it. The most important quotes is
Time-consuming tasks should not be run on the Event Dispatch Thread. Otherwise the application becomes unresponsive.
To address the original question, there are two patterns I usually employ:
Use flags to mark actions that should be executed at some point in the future. When there's no other work for some time I check all the flags, reset them and perform the appropriate actions.
When scheduling work for a worker thread, hold a reference to it. Every time before scheduling new work, cancel the previously scheduled work. Most often used with CancellationTokens in C#/Async.

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.

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