Running a JFrame with a JProgressBar - java

public void myMethod {
MyProgessBarFrame progFrame = new MyProgressBarFrame(); // this is a JFrame
progFrame.setVisible(true); // show my JFrame loading
// do some processing here while the progress bar is running
// .....
progFrame.setvisible(false); // hide my progress bar JFrame
} // end method myMethod
I have the code above. But when I run it, the do some processing section does not process until I close the progress bar JFrame.
How will I show my progress bar and tell Java to continue in the do processing section?

You've got a classic problem with concurrency and Swing. Your problem is that you're doing a long-running task on the main Swing thread, the EDT or Event Dispatch Thread, and this will lock the thread until the process is complete, preventing it from doing its tasks including interacting with the user and drawing GUI graphics.
The solution is to do the long-running task in a background thread such as that given by a SwingWorker object. Then you can update the progressbar (if determinant) via the SwingWorker's publish/process pair. For more on this, please read this article on Concurrency in Swing.
e.g.,
public void myMethod() {
final MyProgessBarFrame progFrame = new MyProgessBarFrame();
new SwingWorker<Void, Void>() {
protected Void doInBackground() throws Exception {
// do some processing here while the progress bar is running
// .....
return null;
};
// this is called when the SwingWorker's doInBackground finishes
protected void done() {
progFrame.setVisible(false); // hide my progress bar JFrame
};
}.execute();
progFrame.setVisible(true);
}
Also, if this is being displayed from another Swing component, then you should probably show a modal JDialog not a JFrame. This is why I called setVisible(true) on the window after the SwingWorker code -- so that if it is a modal dialog, it won't prevent the SwingWorker from being executed.

You would have noticed that when a progress bar is shown, along with processing of the progress bar the actual task is also being done. So you can understand from here that there is multi-threading going on.
In Java you can make a separate thread to just show the progress bar and in main thread you can do your task. So both the processes will run simultaneously and it will serve your need.
*NOTE : the progress shown in progress bar should depend on processing being done in main thread.
you can check these links for Threads & Progress Bar in Java.

Related

Pausing a Swing Thread untill a javafx dialog has closed

I have an action that is written in the event dispatch thread, this action calls a method createDialog() which goes away and creates a Swing Dialog and returns it, after this method call we check if the dialog has been canceled and then it returns the result of this. unfortunately my company want me to change this createDialog() method so that it returns a JavaFX dialog instead of a Swing Dialog.
My problem comes when we check if the dialog has been cancelled, because we are in the Event Dispatch Thread I then need to do the Platform.runLater to put myself into a FX thread but obviously because I have created a new thread the program will run on and not wait for the dialog to close. I have tried to pause the Event Dispatch thread until the Javafx thread has completed but pausing the Event Dispatch thread has resulted in the UI becoming unresponsive.
Is there a way to make the Event Dispatch thread wait for a javafx thread to complete? I am fine with using a jfxPanel but i still seem to have the same problem. I am sure I am doing something wrong and it is actually a simple thing to fix but some advice would be great. (I am not able to change the Action because of company guidelines).
Thanks in Advance.
as a small code example:
//we are currently in the EDT (I can't control the start of this)
//creates the dialog i want this to create the FX Dialog
m_dialog = createDialog();
//because my dialog is in the FX Thread the EDT will hit this part of code before the dialog has been closed.
if (m_dialog.isCancelled()) {
return IActionEnum.eCanceled;
}
return IActionEnum.eCompleted;

Java Swing Progress Monitor for GUI Creation (EDT)

I want to use a progress monitor to show progress during the start of a real complex dialog!!!
The dialog creation is done within the event dispatcher thread. It can take up to 10 seconds, depending on the client system.
My desire is then to see a progress monitor in the foreground which shows status of each current loading part. Meanwhile the Dialog is building up in the background.
The problem is the progressmonitor always freezes until the dialog is started. When the dialog starting is finished the progressmonitor reacts and shows the current state.
I tried a lot of things read in forums, but without two different threads it doesn't work. Here is the example that let both the progress monitor and the dialog creation running in the EDT.
final CVProgressMonitorDialog progressMonitor = new CVProgressMonitorDialog();
progressMonitor.startPollingThread();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
startComplexDialog();
}
finally {
close(progressMonitor);
}
}
});
The CVProgressMonitorDialog is mainly the ProgressMonitor shipped with swing.
The solution is to let the creation of the dialog run in an other thread.
final CVProgressMonitorDialog progressMonitor = new CVProgressMonitorDialog();
progressMonitor.startPollingThread();
new Thread() {
#Override
public void run() {
try {
startComplexDialog();
}
finally {
close(progressMonitor);
}
}
}.start();
Do using the second solution causes potential troubles since swing is not threadsafe?
Is there a general solution to monitoring task within the EDT?
You state:
The dialog creation is done within the event dispatcher thread. It can take up to 10 seconds, depending on the client system.
And there is your problem. You need to run any non-Swing long-running code in a background thread such as that supplied by a SwingWorker, but taking care to be sure that any code that changes the state of a visible Swing component be done on the event thread.
My desire is then to see a progress monitor in the foreground which shows status of each current loading part. Meanwhile the Dialog is building up in the background.
Again, do your work in a SwingWorker-derived background thread, updating the SwingWorker's progress property as the creation progresses, and using a PropertyChangeListener added to your SwingWorker to monitor and to display changes to the progress.
As stated in another answer, you shouldn't do lengthy operations in the EDT. But if you are in a hurry, I've managed a similar situation using a modal JDialog. When a modal dialog is made visible, it will block the thread making the setVisible(true) call and get a dispatch thread of it's own. It can be updated independently from the EDT. Do your progress bar in one of those and it should be fine.

Show loading animation during onclick event in java swing onclick

I have an onClick event in Java Swing.
private void fastForward(java.awt.event.MouseEvent evt) {
loading.setVisible(true);
//some time consuming algorithm
loading.setVisible(false);
}
In it, I perform a operation that consumes a lot of time, so I want to display a loading animation.
I created one as a button with a icon which a loading gif, I set the visibility of the button to false. In the onClick event I set the visibility to true. The problem is that button becomes visible when the whole function executes, which is not what I want. I want the button to be displayed during the execution of the function. How can I set the button to visible during execution.
That is because, only once the UI thread gets free, it can update the UI. This is what you need to do:
private void fastForward(java.awt.event.MouseEvent evt) {
loading.setVisible(true);
new Thread(new Runnable(){
#Override
public void run(){
//time consuming algorithm.
if(done){
SwingUtilities.invokeLater(new Runnable(){
#Override public void run(){
loading.setVisible(false);
}
});
}
}
}).start();
}
Above what happens is this:
UI thread sets the loading status.
UI thread starts a new Thread to execute the command. UI thread is free after this call.
The new Thread computes the algorithm
Once the new thread is done, it requests the UI thread to update the UI
This way, the button wont get freezed. And on completion, UI thread gets updated.
Try using a SwingWorker
It has in built functionality to re-sync with the Event Dispatching Thread through the use of the publish/process methods. It easy to know when its done and has progress update capabilities
Take a look at this, this and this for examples

Progress dialog during tab switch

When the user switches from tab A to tab B it takes a long time (6 seconds), so I put in a progress dialog to let the user know that the app is working on it. The timeline is as follows:
Activity B onCreate - creates ProgressDialog and puts long tasks in a background Thread.
Activity B onStart
Activity B onResume
Activity B appears on the screen
This all works great with one "minor" snafu- the app intermittently crashes because the onResume function references something that is created by the background Thread. It is, in other words, a classic race condition.
To fix the race condition I did a "join" on the thread right before the reference in onResume, but that makes the progress dialog not show up until the background thread is done (i.e. it shows up for a split second and then goes away) and the app acts like it is hung while the background thread is working. Apparently the progress dialog cannot show up until onResume completes.
My question is this: how can I get the ProgressDialog to show up without crashing the program? Or do I need to either get the offending reference out of onResume or live with the app acting hung?
I ended up using a kludgey solution wherein the onResume function waits for the intermediate result that it needs, but not for the entire background thread to finish. This is ugly, I know, but it appears to work.
The better long term solution, I believe, is to separate the creation of the needed object from the long initialization steps that it does when it is created. The timeline would then be:
onCreate
Create object
Create progress dialog
Create background thread, have it do long initialization of object.
onStart
onResume (with no check/sleep loop).
A dirty solution would be to have one ProgressDialog for steps 1 and 2, and then create a second identical-looking one for steps 3 and 4.
Are you using Threading as provided by the Java platform or are you using the Android convenience classes?
I am referring to AsyncTask. More than likely you are running in to issues with your Runnables posting at inconvenient times. The AsyncTask class packages up these features nicely. Subclass AsyncTask, specifying the types for your params, progress, and result. Then hide your dialog in the onPostExecute method, while you perform background work in the doInBackground method.
Sample code:
AsyncTask<Void, Void, Void> parseTask = new AsyncTask<Void, Void, Void>() {
#Override
protected void onPostExecute(Void result) {
// Dismiss the progress dialog
dismissDialog(PROGRESS_DIALOG);
}
#Override
protected Void doInBackground(Void... params) {
// Do background work
return null;
}
};
// Start the background thread
parseTask.execute();
Taken from a live code base. Also don't feel too bad, concurrent programming is easily one of the more difficult systems to program. It is promising that you were able to recognize and identify the race condition.

JProgressBar

any methods available to stop a JProgressBar at runtime?? i wil start a progress bar wen a button is clicked(which wil start a thread at the back ground). what i exactly want is to stop the progress bar wen a deadlock situation occurs in my program.. This is the gist of my program..
Perhaps you can use ProgressMonitor?
From the API documentation:
Deciding Whether to Use a Progress Bar or a Progress Monitor
Use a progress monitor if:
You want an easy way to display progress in a dialog.
The running task is secondary and the user might not be interested in the progress of the task. Progress monitor provides a way for the user to dismiss the dialog while the task is still running.
You want an easy way for the task to be cancelled. Progress monitor provides a GUI for the user to cancel the task. All you have to do is call progress monitor's isCanceled method to find out if the user pressed the Cancel button.
Just some thoughts, hope this helps.

Categories