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;
Related
I'm working on a SWT application in which I'm opening a dialog window. In the dialog window after the user clicks on a button it will execute a task on a different thread. This task will take around 1-2 minutes to complete. After the task is completed, the dialog is updated with the results. I want to prevent the user from closing the dialog box before the task is completed otherwise the task thread tries to update the dialog and swt disposed exception is thrown.
Can anyone tell me how to override the close operation programmatically. I want to avoid creating a custom Dialog class by extending the SWT Dialog class
I have a dialog and when the user clicks the ok button in the dialog, the call goes from client to the server and then starts processing. In mean time when it is in the processing stage when the user tries to click anywhere on the dialog it is getting hanged and then once the process gets complete it behaves normally. So until the process gets complete i dont want the user to click the dialog, even though if he clicks the event should not be detected and dialog should not get hanged.
I dont want use progress monitor, is there anyway to handle this?
This is code I am using after OK button Pressed
`//Server call
startServerProcess(compsTable);
//Async to update UI
Display.getDefault().asyncExec( new Runnable()
{
public void run()
{
label.setText("");
}
});`
Even though the async call is used, when user clicks anywhere on the dialog it shows hanged and says not responding. Any help for this? –
Unless you are doing it asynchronously, it will behave like it does. the SWT is waiting until it gets the response back from the server, and during that time, whatever you do (e.g. click or do other actions) will not have any affect because it is not ready for user interaction yet.
You can run the job in a Thread, but ProgressMonitor was designed to give you a nice modal UI dialog telling you to wait. If you run a separate thread, you'll have to check if they click on the OK button twice, or some other element you left accessible.
I my opinion ergonaut's answer is correct and You should go with threads and asynchronous processing.
But if You insist to do it in one UI(!) thread then disable dialog parent composite, send, receive and process server's response. Then enable parent composite. This will block unnecessary events during processing.
parent.setEnable(false);
send(message)
process(recv());
parent.setEnable(true);
Be aware that user expects some kind of notification when something is processing. Without showing that app is busy user probably assume that application hangs and terminate it.
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.
So using a GUI in java, I am trying to allow the user to press a transfer button which will initiate a method. This method will open up a separate GUI which will ask the user to enter information and then save it when the user has pressed a save button. What I want to do is pause the method after it has opened the separate GUI and continue once the user has hit the save button in that second GUI. Unless there is a better way, I believe that implementing a wait notify method is the best way to go about this but I have been unsuccessful thus far.
Firstly, DON'T (use wait/notify) for any reason within the Event Dispatching Thread. This will cause the UI to stop responding to input events and repaint request, effectively "hanging" your program.
In your case, it would be a simple case of using a modal dialog.
Check out How to make dialogs and Concurrency in Swing
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.