I am writing a quiz program for the Android (written in Java). When the user answers a question (by clicking a button), I want to flash a message on the screen saying whether they were correct or not, followed by a 5 second pause before moving on to the next question.
However, when an answer button is clicked, the program pauses, but does not display the message of correct/incorrect. The message only comes up once the sleep method has finished.
if (correct)
Answer.setText("CORRECT!");
else
Answer.setText("WRONG!");
try { Thread.sleep(5000); }
catch(InterruptedException e) {}
As a bonus, I'd like the answer buttons to be disabled during the pause.
You'll need an AsyncTask for that. Google gives you an intro to it here.
When you Thread.sleep() on the main Activity, you are putting the application to sleep. The AsyncTask will allow you to pause for the 5 seconds, maybe show a little In Progress bar and then pick up from there, without freezing the screen.
Imo AsyncTask is too much for this usecase.
Don't use sleep.
Instead set your correct/incorrect message and than do this:
new Handler().postDelayed(new Runnable(){
public void run()
{
goToNextScreen();
}
}
, 5000);
Use a Handler: you can send a message with a 5000 millisecond delay, disable the buttons and when the message arrives you can re-enable the buttons. See http://www.tutorialforandroid.com/2009/01/using-handler-in-android.html for more info.
You should look into using timers for this. I don't think using threads are sensible for this. Using a timer to move onto the next question would work.
Look at timers here
Hope this helps.
Disclaimer: I have only used timers in Java to do something similar but i'm sure it would work in Android.
Related
I'm currently developing a online version of the game ludo.
The server a client connects to sends a command if enough players connected to notify every client that the game will start.
I want to achieve that a JOptionPane is displayed on the client side that says something like "Waiting for game start" and then continues to wait for a new Input by the server.
At first my code looked like this:
ImageIcon icon = new ImageIcon(getClass().getResource("/resources/waiting.gif"));
JOptionPane.showMessageDialog(null, "Waiting for game start",
"Please Wait",JOptionPane.INFORMATION_MESSAGE, icon);
command = (String) in.readObject();
This worked in so far that the JOptionPane was displayed. Problem: The code got interrupted until the client pressed ok. Then the window was gone and the program waited. So that wasn't what I wanted to achieve.
So I tried to run the JOptionPane in it's own thread and close the Thread when a message was received. This looks like this:
Thread t = new Thread(new Runnable(){
public void run(){
synchronized(this){
ImageIcon icon = new ImageIcon(getClass().getResource("/resources/waiting.gif"));
JOptionPane.showMessageDialog(null, "Waiting for game start",
"Please Wait",JOptionPane.INFORMATION_MESSAGE, icon);
}
}
});
t.start();
command = (String) in.readObject();
t.interrupt();
This solved the problem that the code beneath the JOptionPane wasn't executed but running the code like this displayed the JOptionPane as a blank window with a title. Screenshot below...
http://i.stack.imgur.com/2W42B.png
So my question is: How can I solve this problem or is there any other way to display a JOptionPane without stoping code execution?
The JOptionPane class is, like most of Swing, not thread-safe. Calling showMessageDialog() should only be done from the EDT. The EDT should itself be used only for GUI components and sometimes small tasks, and any heavy processing should be done in background threads.
Now as for your code:
You create a GUI component outside the EDT
You do heavy processing on the EDT afterwards, which does not allow Swing to repaint your component (I imagine that is the problem here)
You then call interrupt on a thread that doesn't really do anything anyway. Interrupting it is not going to make the message go away.
A much better way of achieving what seems to be your goal is to use a SwingWorker. Create a message JFrame with a message or a progress bar or what not, show it, then start a SwingWorker that will do the processing and when done - will hide you JFrame.
I have a dialog containing several buttons. When a particular button is clicked, it's ActionListener iniates a process that takes several seconds to complete. During this time I want to provide some feedback to the user. To take a simple approach, I have a label in the dialog "Computing..." which is initially not visible. A code segment looks like this
button_OpenHoursReport.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
lbl_Computing.setVisible(true);
new runAndRenderReport();
RunAndRenderReport.main(null);
lbl_Computing.setVisible(false);
}
});
The problem is, the lbl_Computing text does not become visible until the RunAndRenderReport is completed. Obviously, that's not much help to the user. Don't know where to go from here. Does this have to do with threads? If so, I could use some guidance on how to get started.
actionPerformed() is executed on the GUI-thread (EDT), so avoid executing intensive operations on it. Instead use SwingWorker.
See How SwingWorker works.
A trick which is much easier than using SwingWorker is to call paintImmediately on your label after calling setVisible(true). You should see the effects - immediately.
lbl_Computing.paintImmediately(0, 0, lbl_Computing.getWidth(), lbl_Computing.getHeight());
But SwingWorker is the way to go if you want your GUI to be responsive in other ways as well while the reporting is running.
Having the following szenario: blurring a textBox (input) writes text to my status-Box (in certain conditions), and clicking a button also writes text to the status-Box.
Now when clicking the button it will blur my textBox if it is focused and that will cause the status-Box to flicker as first the blurHandler will write its result and then the clickHandler.
As i want the result of the clickHandler to appear my idea is to let the blurHandler place an event at the end of the queue which checks whether a clickHandler has written a result before.
In Swing I would try SwingUtilities.invokeLater(Runnable).
The equivalent in GWT is said to be the Scheduler but those deferred or finally commands seems always to run after the current event and before the next.
So far i use Scheduler.scheduleFixedDelay with 100ms delay and hope it comes after the clickHanlder in each browser.
See similar problem with answer.
I think there must be a better solution for this.
How to really add an event to the end of the queue or is it impossible due to limitations of HTML?
Try:
Scheduler.get().scheduleDeferred(new Command() {
#Override
public void execute() {
.......
}
});
See
Class Scheduler
I have developed a simple MIDI application that allows me to play MIDI notes, in order for the user to be able to interact with the UI whilst the MIDI sounds are playing I have put the logic necessary in an anonymous subclass like so:
public static void Play()
{
new Thread(new Runnable()
{
public void run()
{
if (!_sequencer.isRunning())
{
try
{
_sequencer.setSequence(_sequence);
_sequencer.start();
}
catch (Exception e)
{
Logger.Add(e.getMessage());
}
}
}
}).start();
}
Although the music begins to play the UI still fails to respond when I click on a ComboBox for example, I have something similar working fine in C#.
Is there some sort of caveat to thread in Java that would explain the behaviour i'm seeing?
(The Java API I'm using if it helps - javax.sound.midi)
Thanks for your time.
Edit:
Click around the UI a little more and noticed something interesting; everything seems to work fine with exception to two ComboBoxes in the top left most corner, I've tried deleting them and replacing them but makes no difference. The boxes change to blue when clicked (as it would normally) but the drop down box does not appear below it and the colour does not return to it's default when focus is on another UI component. Could it be a bug introduced by NetBeans perhaps?
Example:
Edit 2:
Well after much trial and error I have finally found the cause of the problem, the threading works great. The problem was that NetBeans has somehow realigned my UI components which causes the Window to fill the screen, manually resizing and testing the ComboBoxes showed that they actually worked fine.
Thanks for everybodys feedback!
What does the combo box do when it's clicked? Does it interact with the _sequencer? Furthermore, was your sequencer created on the UI thread? I would suspect that while you're invoking the start method on a separate thread, the sequencer still runs on the context where it was created (i.e. UI thread).
Try creating the sequencer on the playing thread (i.e. NOT the UI thread) and see if that frees up your UI.
Well after much trial and error I have finally found the cause of the problem, the threading works great. The problem was that NetBeans has somehow realigned my UI components which causes the Window to fill the screen, manually resizing and testing the ComboBoxes showed that they actually worked fine.
I am building a swing application. At some point, I have to start an "animation":
...
jpanel1.setBackground(Color.Black);
Delay(milli)
jpanel1.setBackground(Color.White);
...
and so on.
The gui itself and all the logic behind it work.It is just this time depended color-changing that does not. I have read, that swing is not thread safe, but all the examples I found showed me how to start another thread (for example in the background) but never how to stop the current swing-gui thread.
Edit:
The application should work as following:
configuration files are read, jframe is set up.
some simple questions are beeing asked
a dialogue is opened, which explains the animation.
after the user clicked "ok" the animation - some color flashing - is started. the color and the delay between the color-changing is depended on the configuration
another dialogue is opened and the programm continues -> new jpanel inside the jframe, buttons and so on.
the online thing that does not work are the delays between the color-changing. I understand now why it does not work and I am trying to build a timer, which activates a actionlister, which then changes the color and stops the timer... it just seems so much work for a simple delay... and I have to reorganize the entire animation in the application.
Take a look at: https://timingframework.dev.java.net/
and the samples that come in http://filthyrichclients.org/
They provide some very good information on how animation work and using the Timer framework. You'll have a good understanding of how it works.
I did a sample animation here with Swing after reading those:
count down demo app http://img580.imageshack.us/img580/742/capturadepantalla201004wd.png
Java application featuring blog.stackoverflow.com page ( click on image to see the demo video )
But I'm not even sure what is what you want to achieve.
EDIT
I read about the timing framework to understand better what is all about, but I actually didn't use it ( it is useful to create animations with no linear times - ie no every second as mine, but things like 1, 5, 3, 2 seconds )
The code I'm using in the demo above is exactly this:
final Timer imageTimer = new Timer();
imageTimer.schedule( new TimerTask() {
public void run() {
changeImage();
}
}, 0, 10000 ); //<-- every 10 seconds.
The animation for the "stackoverflowing" and the count down use a similar approach.
You do not want to stop the GUI thread, even if you want to have a flashing effect. This is because other basic actions, like repainting when the GUI is hidden by other windows, will be stalled. Take a look at Timer. It will allow you to have an event fired on an interval and you can handle that, in the GUI thread, in your actionPerformed method.
You will want to use the javax.swing.Timer class and not the java.util.Timer class.
The later is preferred when you need general timing the former is preferred for UI updating/changes.
See http://java.sun.com/docs/books/tutorial/uiswing/misc/timer.html
You may also want to look at https://timingframework.dev.java.net/.
Do the timer on another thread and when the timer goes off it can send an update message for the animation to draw the next frame.
Another consideration is the delay itself. Don't pick a fixed delay-interval. Old games used to do that and they become unplayable on faster computers. Instead what the newer games do is use the speed of the current CPU to figure out how many update events they need a second at runtime, call it a 'delay-factor', and is set when the program starts up. . The timer uses the delay factor so the animation displays correctly even on machines of different clock-speed.