JButtons don't imediatly change on mouse event - java

I'm using the java swing library to develop a board game called DAO.
The problem is that after the human player makes its move, by clicking on the JButton with the piece image that he wants to play, I call the computer AI routine but inside the mouse event function. By doing this only when the function returns, the computer ends its turn, do the JButtons refresh their Images (setIcon comes in).
I'd like to know how can I force the JButtons to change their image at the moment they are clicked and not only when the mouse event function ends (as I need to handle data inside it).
I've tried all of this
myButtons[i][j].setIcon(xIcon);
myButtons[i][j].revalidate();
myButtons[i][j].repaint();
myButtons[i][j].validate();
None worked.
Thx in advance

You may want to try putting the action performed upon clicking the JButton into a Swing worker. This will allow the task to go on in the background, while the user can still click other buttons, etc.
See http://java.sun.com/docs/books/tutorial/uiswing/concurrency/simple.html.

There is a single thread used for all Swing activity.
Here's the process.
One event appears on the event queue
it is pulled from the queue and executed by The AWT Thread
Any new events created while this is executing are placed on the queue to be held until the currently running AWT event returns.
The event executing returns and the next event on the queue is dequeued and executed.
This means that if you need to do anything that takes more than, say 1/100 of a second or so, you shouldn't do it any thread started from a swing event. Instead, spawn your own thread and return the swing thread to the system so the GUI can be updated.
Now, your thread MUST NOT update any GUI objects! If you need to update a GUI object, use invokeLater to place your code back on the AWT thread.
New Java programmers not conforming to this rule and executing tasks on the AWT thread is almost certainly the biggest reason people think Java is slow.

Related

Interactive background

I'm designing a game where you get to the edge of the screen the screen will shift to a new panel of the same map similar the first Zelda game. Which method would be more efficient and or effective, having a thread running using repaint() or would using javax.swing.Timer and calling super.paintComponet work better?
Usually for simple animations, you can use javax.swing.Timer But it looks like you are into a more complex game. If you continue to use swing.Timer and if your execution of the codes are not fast enough, it may affect the painting of your components causing your UI to be irresponsive.
You can construct a game loop and render according to the frame rate you wanted by invoking Thread.sleep(delay) via a worker thread remember do not run it in the Event Dispatch Thread, else your UI will also become irresponsive.

Does the following situation needs synchronization?

I have a thread which enables and disables a button in certain random time, if the button clicked when it is enabled an action performed will be executed which will change the image of the button. I am concerned about the synchronization here. Suppose the button is about to get disable and got clicked, so now both threads will execute one to disable it and other to change the image. How should I synchronize this?
All Java GUI toolkits (be it Swing, Apache Pivot, JavaFX, AWT, SWT, Android...) are single-threaded. This means that all listeners will always fire in the same thread. So:
no, you don't need to perform any kind of synchronization,
yes, you need to take care so that disabling and enabling the button happens in the gui thread (wahetever it's called). The exact code is toolkit-specific.

Correct concurrency approach to swing animation?

I am about to write an animation in which a character on a JPanel moves left/right when the user presses (and holds) the appropriate keys.
Now, since I am new to concurrency I want to ask : should the code handling the animation (namely the method that will move and repaint the character as long as the key is held) be executed on a worker thread or the event dispatch thread ?
I read the tutorials on concurrency in swing, and it seems that stuff that changes the components (in this case it's painting JPanel) should be on the event handling thread, but on the other hand that would freeze all the other events as long as a key would be held right ?
For example a user won't be able to pause the game while he's holding the go-left key, if I understand this correctly. So which approach is correct and why? Or maybe there is totally different way to make such an animation ?
Thank you in advance!
All the Drawings Paintings need to be done on EDT thread. Never on any other Thread . Use
SwingUtilities.invokeLater() .. for your painting. You can do calculations like what will be the next postion of your character on Worker Thread. You won't have any unresponsiveness if you are doing creating and using Swing Classes on EDT. just Make sure that your computation is not too long. For Animation whenever you find the next positon of your Character just call
SwingUtilties.invokeLater to update changes on UI

Using Threads to perform operations on same jframe

i need to develop java code to have JFrame with a text filed and button.Using Threads,i need to update time for every one minute in the title bar of JFrame.Using Another Thread i need to display textbox value in the console when a button is clicked.I have code for performing both operations (updating time for every min and getting text box value)but i dont know how to add two threads in same class.if anyone knows pls help me out
What you are asking is a dangerous thing to do in Swing. Swing components are not thread-safe and should only be updated from the Event Dispatching Thread (also known as the EDT or Swing Thread). To do this, Swing has utility methods such as SwingUtilities.invokeLater(Runnable) which will execute the code in the Runnable (at some point in the future) on the EDT. The idea is that you place your code to do Swing-things (like update the Title of the JFrame with the time) inside of a separate Runnable and pass it to invokeLater().
To do this, you can create an anonymous Runnable class:
Runnable updateJFrame = new Runnable () {
public void run () {
myJFrame.setTitle("My New Title");
}
};
SwingUtilities.invokeLater(updateJFrame);
Using invokeLater() also ensures that the components get refreshed/repainted properly after they have been updated. (The behavior you are seeing when using statics may actually be a refresh/repaint issue.) The moral of this story is that if you manipulate Swing components on a non-EDT thread, all bets are off.

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);

Categories