JOptionPane displays a blank window - java

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.

Related

Can't make new game until thread stops

I am building a game and I am trying to create "New game" button.
In the game I have thread that delays computer's move so I can see it step by step by using thread.sleep.
My problem is that I can't make a New Game until this thread is over.
If I manually stop it, I will get InterruptedException.
What can I do in order to do it?
My game is placed on JPanel which is placed on JFrame.
I tought that if I dispose the JFrame and create a new one, it will destroy the JPanel and all it's content and create a new one all over. but it's not working either.
Any suggestions??
Thanks in advanced,
Ron.
For stopping a Thread, see: https://stackoverflow.com/a/8581317/1178781
The InterruptedException is thrown if you stop a thread while it is sleeping. Just wrap the sleep call in a try...catch (with the catch doing nothing) if you do not want to handle this exception.
See the Java API: http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html#sleep(long)
Also see: How to programmatically close a JFrame

not able to show data in a jTextField

I am writing a socket programming. It has GUI for server and client. In the server GUI there is a textfield which shows the word requested by user.
But I am having problem in showing the word.
I have tried
txtWord.setText(sentword);
It is not showing the word in the textfield. But when I write this
txtWord.setText(sentword);
JOptionPane.showMessageDialog(null, "the requesed word is: "+sentword);
then it shows the word in textfield and also shows it in the messagebox.
I have tried repaint() but it dint work.
Please suggest me some solution as soon as possible
as #Binyamin Sharet correctly commented, you have a Concurrency in Swing issue.
your Swing GUI doesn't care about long and hard tasks you're running in the background
even JTextField#setText() is declared as thread safe, output from Socket (i.e.) by default never notified Event Dispatch Thread
correct way could be to use a SwingWorker that has been created specifically to run long and hard tasks background to the Swing GUI and output to the GUI on event thread or EDT
or even easier is to use a Runnable in a Thread but making sure that all output to the Swing GUI is queued on the Swing event thread by placing it in a Runnable and calling it with invokeLater()
A dirty hack is to wrap code lines like so:
txtWord.setText(sentword);
JOptionPane.showMessageDialog(null, "the requesed word is: "+sentword);
into invokeLater(), but in this case your GUI will be unresponsive to Mouse or Keyboard events until Socket (in your case) ended
txtWord.requestFocus();
textField does not show up until the window is over the textField and back or it gains focus, until Clicking on it. So... just request focus.
Also if check the text size if you had set while creation.Sometimes text not displayed if there is mismatch in size
eg: txtWord.setSize(200, 24);

JInternalFrame won't appear

I have a java class called GameUpdater which extends JInternalFrame.
It used to extend JFrame when I ran the class as a program by itself, but I changed it to JInternalFrame to become part of a larger application - now accessible from a menu button.
The function being called when I press this menu button is as follows:
private void update(){
GameUpdater gu = new GameUpdater();
desktop.add(gu); //add to JDesktopPane
gu.setSize(400, 300);
gu.setVisible(true);
gu.readMatches();//this function takes ages
gu.setMatch("Updating database...");//this is some output to the user, displays info in the internal frame
//try and insert into database
for(Match m : gu.getMatches()){
db.insertMatch(m);
}
gu.setMatch("DONE"); //now it shows the frame, way too late
}
The method gu.readMatches() takes a long time to execute, so it periodically updates content in the JInternalFrame to display its progress. However the frame is not being shown until this update function is complete!
It's like setVisible(true) is waiting until the end of the function...
It worked absolutely fine when it was a JFrame. Is there any weird property of a JInternalFrame that would cause this?
Cheers
It sounds like you're executing a time consuming process inside the Event Dispatching Thread (EDT), this will prevent the event queue from process (amongst other things) repaint requests.
This will cause you program to appear as if it has "hung".
You need to off load this task to a background thread.
Have a read through Concurrency in Swing, especially the section on Worker Threads and SwingWorker
The problem is that you are blocking your EDT this can be taken care of by simply creating a new Thread/Runnable thar calls gu.readMatches(); the method:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
gu.readMatches(); //gu will have to be declared `final`
gu.setMatch("Updating database...");//this is some output to the user, displays info in the internal frame
//try and insert into database
for(Match m : gu.getMatches()){
db.insertMatch(m);
}
}
});
ofcourse though you might want to implement a JProgressBar so the user can keep track of of how far the reading is.

Java - Swing JLabel updates too quickly?

In a method of a class, I update the same label twice. The first time, it shows the user message to wait, but the second time shows the user the completed message. Something like the following:
MyClass{
myMethod(){
jLabel.setText("Please wait...");
//does calculation
jLabel.setText("Completed successfully!");
}
}
When I run the app, all I see is the "Completed successfully" message. Is the JLabel updating too quickly? How do I control it? I tried using the following but no luck :(
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
jLabel.setText("Please wait...");
}
});
If the calculation is done in the event dispatch thread, then it blocks the thread and prevents it from doing all its repaintings. You must do the computation in another thread, and have this thread change the label text when it ends (in the event dispatch thread, using SwingUtilities.invokeLater, or by using the SwingWorker mechanism). If the computation is really fast, it's not worth it, though, because the second text will appear so quickly after the first one that you won't even notice the first one.
Have a look at SwingWorker, which is designed for such use-cases. Its javadoc contains a useful example.
if you want to delay some Action/Event then use javax.swing.Timer, or wrap your code to the Runnable#Thread,
notice: never use Thread.sleep(int) durring EDT, your GUI freeze until Thread.sleep(int) ended
example for javax.swing.Timer & Runnable#Thread & Freeze GUI by implements Thread.sleep(int) durring EDT here
Possibly because your calculations are happening too fast. Did you try putting a delay after your calc.
Also as Nizet points out above if this is happening in EDT the component will not repaint until end of the thread which means it will take the last set value.

Pause execution in Java GUI

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.

Categories