I've got a button that kicks off a background thread to do some work and I am trying to use a ProgressDialog to prevent the user from double clicking that button (or any other ui elements) while that work is being done. The first thing I do in my buttons onClick code is to display the progress dialog, which takes over the screen. The problem I am seeing is that if I rapidly tap this button, sometimes two or more presses will register before the ProgressDialog is shown. This leads me to assume that ProgressDialog.show() is returning before the ProgressDialog is actually visible.
Can anybody confirm this? Also, is there a way to change this behavior, or at least get a notification of when the dialog is actually visible? I saw Dialog.onStart() but given the javadoc, this appears to be called before the Dialog is actually visible...
UPDATE:
While it appears that there is no good way of solving this problem in general, the following works for my situation where my work is done by an external thread and the amount of work to do takes longer than the time it takes for all the button clicks to be processed:
void myOnClickHandler() {
if(myButton.isEnabled()) {
myButton.setEnabled(False);
// do work here
// setEnabled(true) is invoked at the end of my spawned thread's run().
}
}
No.
The problem is you clicked many times before the click event is delivered. (i.e. it is queued before you run ProgressDialog.show().)
From what I've noticed in Android you can double click on a button rapidly and have the onClick listener fire twice (or even more) regardless of the code in the listener (even if you disable the button immediately).
I reported a bug a while ago here: http://code.google.com/p/android/issues/detail?id=20073 but of course these things tend to go "unnoticed" by Google. Feel free to star it in hopes of getting Google's attention
Related
I am working on an application that will have the following feature:
The application will have a "Load Image" button to open an image and settings modal dialog. It will need to block until that dialog returns, either with the results of the processing or null if the user changed his mind.
The image and settings dialog will allow the user to select an image using a JFileChooser dialog and to specify to what level of detail to process the image. Clicking a "Load" button will open a load dialog.
The load dialog needs to be a custom-designed dialog that reports in detail about the time-consuming processing of the image. If the user allows the processing to finish, it needs to close and return the object back to the original dialog, which needs to close and return that object back to the application. If the user decides it is taking too long to perform the processing, he can cancel the load, closing the loading dialog and returning to the image and settings dialog.
Conceptually, this does not seem so difficult to me. However, when I try to determine how to get this to work within Swing, somehow I cannot put it together. From what I've read, GUI components need to be instantiated in Swing's event thread since many of them are not thread-safe. These same components need to block on calls similar to (but not the same as, since I need to write custom components) the JOptionPane.showInputDialog() methods. But these calls need to instantiate new components in the event thread and wait for events to occur in the event thread before returning a value to the application. Compounding this with the fact that I need a dialog to pop up from a dialog, I feel quite lost.
I have read the Java Tutorial on dialogs and several posts on StackOverflow and other sites trying to determine how I can design classes that work correctly. Somehow, I just don't understand how this can work at all (isn't the event thread going to sleep after the first blocking call?), and how I can write the custom classes I need to make this work. Frankly, I am not certain I understand my confusion enough that I was able to explain it.
Could someone please explain what goes on under the hood when modal dialogs have been instantiated? How I can write dialog classes that behave the way I need as described above?
The application will have a "Load Image" button to open an image and settings modal dialog. It will need to block until that dialog returns, either with the results of the processing or null if the user changed his mind.
OK, so this dialog will need to be modal. That much we know.
The image and settings dialog will allow the user to select an image using a JFileChooser dialog and to specify to what level of detail to process the image. Clicking a "Load" button will open a load dialog.
OK, so the load dialog will need to be modal off of the image and settings dialog. No biggie there either.
The load dialog needs to be a custom-designed dialog that reports in detail about the time-consuming processing of the image. If the user allows the processing to finish, it needs to close and return the object back to the original dialog, which needs to close and return that object back to the application. If the user decides it is taking too long to perform the processing, he can cancel the load, closing the loading dialog and returning to the image and settings dialog.
OK, so the load dialog code will need to instantiate and execute a SwingWorker to do the time-consuming image processing in a background thread, and then have the SwingWorker use its publish/process method pair to push information about the processing details back to the load dialog.
...From what I've read, GUI components need to be instantiated in Swing's event thread since many of them are not thread-safe.
Correct.
These same components need to block on calls similar to (but not the same as, since I need to write custom components) the JOptionPane.showInputDialog() methods.
And this is what a modal JDialog allows you to do. Another option to keep in mind is to use a JOptionPane and pass in a JPanel with whatever GUI you want the JOptionPane to display. JOptionPanes are surprisingly flexible and useful.
But these calls need to instantiate new components in the event thread and wait for events to occur in the event thread before returning a value to the application. Compounding this with the fact that I need a dialog to pop up from a dialog, I feel quite lost.
Again it's simple. The load dialog will call a SwingWorker which will communicate back to the load dialog.
Could someone please explain what goes on under the hood when modal dialogs have been instantiated?
Now you may be asking a bit too much for the volunteers on this site to do, since this question would probably require someone to write a complete tutorial to answer, and it has been asked and answered before, so the information should be discoverable by you. If you really want to see what is going on under the hood, you should first do the preliminary research on the subject yourself, look at the source code, and if still stuck, ask a much more specific and answerable question after first doing your own due diligence work.
Modal dialogs started from the primary event loop spawn a secondary event loop that remains active while the primary loop is blocked. See java.awt.SecondaryLoop.
How do I make it so that the program doesn't keep reading in code until the button is clicked?
Why?: I have a 10x10 grid with buttons in each part and then code running depending on what is clicked. However, my program keeps reading in code so there is never a choice being made and it gives me error. I tried giving it a infinite loop until a button is pressed, but that doesn't work out so well
-edit
I'm a complete beginner with Java.
This is a picture of the GUI
http://imageshack.us/content_round.php?page=done&l=img843/5351/sascp.png
What I want is for the code to not keep running step by step until I click a button.
E.G.:
create gameGUI
wait until and check which button is pressed
if(buttonClicked[i][k] == something){
System.out.println("lool");
}
But what's happening in my code is that it creates the gameGUI and then because the user isn't fast enough to click it just skips over the if statement or gets a run-time error because nothing was pressed.
In both Android & Swing (& I'd expect J2ME), buttons fire events when told to do so (by activating them). You would generally just wait for that to happen before doing anything, and not bother with what the rest of the GUI is doing (or not doing) at the time.
Or in other words:
Add an ActionListener to the buttons.
In the actionPerformed() method, insert the code that you have above.
Also
The code snippet provides almost no useful information. For better help sooner, post an SSCCE.
That GUI looks like Swing to me. If it is not, then what is it?
Please always copy/paste run-time errors.
I'm really new to Java, especially working with GUI in Java.
I want to put a progress bar in my program, where it updates its value each time after certain amount of work has been done. Right now I have a button that executes a method when pressed, and I put setValue() function (with the value that I want) each time after certain work has been done in that method. However, when I press the button, the button seems to be stuck pressed while the method continues (the method takes a while to finish executing), and the progress bar doesn't get updated until all the other things has been done in the ButtonListener, so it goes directly to 100% after it's done).
What am I doing wrong?
Thanks in advance.
That is, most probably, because you are doing all work in main thread so it hangs your UI until all work is done. You should not do this. You should use separate EDT for such operations. What you should try is do your update progressBar job in separate EDT. Use SwingUtilities.invokeLater(Runnable r) for this.
in echo 3 i have a problem setting focus on a specific text field in a new screen. The probelm occurs when a user holds their mouse on the reference button on the previous screen as opposed to just a simple click.
it looks similar to this:
public void display screen {
build window
if window isnt null{
build screen
if screen.textfield isnt null{
Thread t {
thread sleep 10000
screen.textfield.setFocus
}
}
}
}
in the pseudo above the focus would be set if the user user held the reference button down on the screen before for less than 10 seconds, in which case the focus would not be set until the remaining thread time passed. this isnt good because it take too long; and lower wait delay doesnt insure that the focus will set at all because the user might hold the key for longer.
I have tried launching multiple threads and using timers to hammer the focus in but that didnt work... is there something im missing about how the code is built internally because it seems that the whole thing is built despite the fact that the user hasnt let go of the button.
If thats the case is there a way to do it on release?
Thank You
Found a solution. The problem was with using IE6. I presume the order in which it builds is different to that of IE7+.
I am creating a matching game for Android, and when the user gets a match, a dialog box should pop up saying "Match!" I cannot figure out how to do this though. If I use Thread.currentthread().sleep, the dialog never appears.
android.app.AlertDialog a = new android.app.AlertDialog.Builder(match.this).setTitle("Match!").show();
Thread.currentthread().sleep(1000);
a.dismiss();
Nothing happens - the program just hangs for a second. I would like it to pop up for just 1 second, or if there is another sort of popup type thing, that would be good too.
You're trying to show a text message in a popup for a short period of time on the screen?
For these kind of alerts toasts are great:
Toast.makeText(this, "Match!", Toast.LENGTH_LONG).show();
Is that what you are looking for?
Here is the Java Doc.
The dialog is shown in the current thread but you are putting the thread to sleep so it never shows up. Other than event throttling, there are few cases where you want to call sleep with a substantial delay from the UI thread.
In this case using a Toast is easiest as the previous poster suggested. A couple of other ways to handle work you want done in the future
Java Timers. The action will happen
on a different thread so you have to
be carefull what gui calls you make
Views have a postDelayed(Runnable action, long delayMillis) method will cause the Runnable to be executed on the UI thread after roughly delayMillis.