Display.getDefault().asyncExec not running correctly - java

I am using eclipse's jobs API to run big task as a job, once task is completed I am setting boolean variable to true and if that variable is true I am executing WizardDialog in UI thread. My current code looks like this:
Job longRunningJob = new Job("Long running job...") {
#Override
protected IStatus run(IProgressMonitor monitor) {
boolean shouldShowDialog = doLongRunningJob();
if(shouldShowDialog) {
Display.getDefault().asyncExec(new Runnable() {
#Override
public void run() {
//Will open wizard dialog here
WizardDialog wizardDialog = new WizardDialog(Display.getCurrent().getActiveShell(), new TestWizard());
wizardDialog.setBlockOnOpen(true);
wizardDialog.open();
}
});
}
}
}
longRunningJob.setUser(true);
longRunningJob.schedule();
My problem is run inside Display thread not executing in reliable way, means sometime it goes inside run method where as sometimes it doesn't, I tried putting breakpoint inside run method and testing it out but same happens.
My question is, is what I am doing is correct way? Is this expected behaviour? So how do I handle this scenario ie once shouldShowDialog is true how do I execute code inside Display thread?
Edit: One behaviour I observed while debugging is dialog gets displayed but suddenly it get closes, I think it's exiting the thread.

The problem with disappearing dialogs is most commonly caused by using currently active Shell as the parent for the dialog. E.g. if there is a ProgressDialog open when you create your dialog then that other dialog will be the parent of your dialog. And when the other dialog closes, so does yours.
Instead, use something like:
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();

Related

Perform an Action on showing AlertDialoge, then dismiss

I would like to start an AlertDialogue showing a loading message and a ProgressBar icon, then on showing the dialogue I would run the heavy processing with the ProgressBar spinning, and finally cancel the dialogue when the processing is over.
I have tried putting the logic on setOnShowListener of the alert dialogue which was not carried out. Then, I have tried starting the dialogue then using a delayed handler like the following:
new Handler().postDelayed(new Runnable()
{
#Override
public void run()
{
// heavy procssing logic
// alert.dismiss();
}
}, 1000);
Though, the ProgressBar icon stopped spinning, so I assumed that my heavy processing blocked the UI. How do I achieve what I need. Thanks.
Edit: I have replaced the handler with new Thread() and everything worked properly. Would this approach cause any problems like memory leaks?
Create a new AsyncTask to do your work, this will cause any code placed in the “doInBackground()” method to be ran in a background thread, you have pre-execute and post-execute to run code on the main thread, my recommendation is create an alertDialog in the pre-execute methods and close it on the post-execute, using “publishProgress()” method In the doInBackground method to update your dialog as you need.
Otherwise instead of an alertDialog (or as well as) you can use a progressBar, simply have it in the view preciously, instantiate it as you normally would.
<ProgressBar
android:id=“+id/progressBar”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:centreInParent=true
android:indeterminate=true
android:visibility=gone />
ProgressBar progressBar = view.findViewById(R.id.progressBar)
Now when you want to show the progress bar use
progressBar.setVisibility(visible)
Or to hide
progressBar.setVisibility(gone)

JavaFX 8 initialize method

So I am trying to do a chat type program using JavaFX for the GUI. I have it so a class that acts as a server will loop and keep adding client connections to it.
public void serverconnection()
{
// portnumber was saved from constructor
try (ServerSocket socket = new ServerSocket(this.portnumber))
{
// loop is a bool set to true
while (loop)
{
// this class extends Thread and has its own overwritten start method
new myclass(socket.accept()).start();
}
}
catch (IOException e)
{
System.exit(404);
}
}
so the problem is (I am assuming) was, this loop keeps looping until the program closes. but since I was calling this within the JavaFX's initialize method
public void initialize(URL url, ResourceBundle rb)
{
// constructor, nothing here is needed for this post
myclass z = new myclass(45234);
// problem here, since this has a loop, but
z.serverconnection();
// gui wont load till after this is done
// but serverconnection is only done after program ends
}
the problem with this is, apparently, the GUI will not load until AFTER initialize has finished, but it will not finish until program closes. After google searching, I could not find any fix for this. I need a way to call a method that will do all this, AFTER initialize method has finished. My client side class is similar to this, but the methods to connect on that are activated on events when clicking a login button. For this serverside one, I am trying to start without any interaction with the user. so is there a way to call a method or make this work AFTER initialize method has ran?
You might want to run this loop in a thread, so do something like
Thread t = new Thread(z::serverconnection)
t.start()
If you do this at the end of your initialization() method, it will run exactly then.
This will start a thread which runs forever; you might want to add a feature for interrupting the thread when the program is supposed to be terminated.
Remember that for changing anything in the GUI you need to sumbit a task via Platform.runLater(). This is because the GUI may only be modified from within that one thread. So in order to modify anything, you have to wrap that in a Runnable and submit it for execution.
You can do that in this way:
Platform.runLater(new Runnable() {
#Override
public void run() {
doWhateverNeedsToBeDone();
}
});
In Java 8, you can do anything of the following, depending on the extent of the work to be done:
Platform.runLater(() -> {
doWhateverNeedsToBeDone();
});
Platform.runLater(() -> doWhateverNeedsToBeDone());
Platform.runLater(this::doWhateverNeedsToBeDone);
The latter only works if doWhateverNeedsToBeDone() is a method of this.

eclipse wizard performFinish slowness

I am creating an Eclipse wizard... I am overriding the method
public boolean performFinish()
Inside the method, I want there to be a progress monitor... So I am doing the following:
IRunnableWithProgress op = new IRunnableWithProgress() {
public void run(IProgressMonitor mainMonitor) throws InvocationTargetException {
//do stuff
}
};
I have ran the wizard in debug and have found that it is not my code that is making it run slow. I can simply print out something with the monitor and it still takes a little while for the performFinish to be kicked off. Is there something I am missing with performFinish? Has anyone else seen this issue?
I have not seen this.
You would normally use the progress bar built in to the wizard like this:
getContainer().run(true, true, runnableWithProgress);
in the performFinish.
You wizard should call
setNeedsProgressMonitor(true);
in its constructor to enable the wizard progress monitor.

Unable to change button text to icon immediate after click button in java swing

I have written following code.I have not shown full source but psudo code.
class UI extends JFrame
{
//created UI with one Button
onButtonclick()
{
//did some operation before set icon to button
//say opened fileopen dialog and get file
button.setText("");
ImageIcon progressbar = new
ImageIcon(DatasetExporterUI.class.getResource("/progreassbar.gif"));
buttonExport.setIcon(progressbar);
// did some database operations
//again removed icon from button
button.setIcon(null);
button.setText("click");
}
}
When I click on button It opens file open dialog and and button text get set to empty.
But It doesn't set Icon to button.When all Database operation are done which are performed after Icon set to button that time Icon is appeared on button.
Why this behavior is?
How to set Icon to button and do some Database operations and again remove it?
Thank you. :)
The GUI system can only do one thing at a time, like most code (except for code that uses threads). Calling your listener is a thing. The GUI system cannot do anything else while your listener is running.
Your database operation needs to run on another thread (which you can create) and then update the GUI when it's done. Something like this:
void onButtonPressed() {
// The code to open the file dialog goes here
button.setText("");
ImageIcon progressbar = new
ImageIcon(DatasetExporterUI.class.getResource("/progreassbar.gif"));
buttonExport.setIcon(progressbar);
new Thread() {
#Override
public void run() {
// do some database operations here
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
//again remove icon from button
button.setIcon(null);
button.setText("click");
}
});
}
}.start();
}
Code in different threads runs at the same time. This is convenient but dangerous. Be extremely careful when accessing data from the new thread - if one thread changes a field and the other thread reads it, the results might not be what you expect. The simplest thing to do is to make sure the main thread doesn't change any variables used by the new thread while it's running.
When your database operations are finished, you can't set the button back to normal by just calling setText. Only the main thread is allowed to affect the GUI - what if the main thread was drawing the button on the screen at the same time the database operation thread was changing the text? The button might be drawn incorrectly. So you need to call EventQueue.invokeLater which tells the GUI system to run your code in the near future when it's not busy. The code inside new Runnable() {} is like the code in the button listener - no other GUI-related code will run while it does.
This should work:
Image progressbar= ImageIO.read(DatasetExporterUI.class.getResource("/progreassbar.gif"));
buttonExport.setIcon(new ImageIcon(progressbar));

Applet with JDialog not hiding correctly in Mac OSX

I have an applet that calls a JDialog that contains a JProgressBar component. I subclass the JDialog to expose a method to update the JProgressBar, something like:
public class ProgressDialog extends javax.swing.JDialog {
public void setProgress(double progress) {
jProgressBar1.setValue(jProgressBar1.getMinimum() + (int) (progress * jProgressBar1.getMaximum()));
}
...
}
I use this dialog in the following manner:
public void test() throws Exception {
progressDialog = new ProgressDialog(null, true);
try {
progressDialog.setLocationRelativeTo(null);
// show the dialog
EventQueue.invokeLater(new Runnable() {
public void run() {
progressDialog.setVisible(true);
}
});
// business logic code that calls progressDialog.setProgress along the way
doStuff();
} finally {
progressDialog.setVisible(false);
progressDialog.dispose();
}
}
It works fine on Windows/any browser. However, when invoking the above function on Firefox 2/3/3.5 on a Mac, the progressDialog is displayed indefinitely, i.e. it doesn't close.
I suspected that calling setVisible(true) inside the EventQueue was causing the problem, since it's a blocking call and might block the queue completely, so I tried changing it to:
// show the dialog
new Thread() {
public void run() {
progressDialog.setVisible(true);
}
}.start();
With this change, the progressDialog now closes correctly, but a new problem emerged - the contents of the dialog (which included the progressbar, an icon and a JLabel used to show a message string) were no longer shown inside the dialog. It was still a problem only on Mac Firefox.
Any ideas? I realize it's probably some AWT threading issue, but I've been at this for a couple of days and can't find a good solution. Wrapping the doStuff() business logic in a separate new Thread seems to work, but it's not easy to refactor the actual business logic code into a separate thread, so I'm hoping there's a simpler solution.
The envt is:
Mac OSX 10.5
Java 1.5
Firefox 2/3/3.5
Found out that the problem was that the applet function was executing inside the AWT dispatcher thread, therefore the thread blocks and no events are processed until the applet function finishes execution.
Solution was to move the processing logic into a separate thread spawned by the ProgressDialog object before calling setVisible(true). setVisible(true) would block the main thread but still allow the event dispatcher to continue processing, hence rendering the contents of the dialog until the spawned thread calls setVisible(false) to hide the dialog.

Categories