I try to move a JLabel from Position A to Position B sequential in same X and Y Steps.. The Method works correctly, but doesnt't update my gui..
I Show you my code in the following:
When I don't call the .join() Method, the code works, but don't wait with execution on my another Thread... I need that this function don't call when it actually runs.. Can anybody help me?
Thread MoveThread = new Thread( new Runnable()
{
#Override
public void run()
{
for (int i = 0; i<Const.SteinVerschiebenSchritte; i++)
{
try
{
p_lblToMove.setLocation(p_lblToMove.getLocation().x + x_schritt, p_lblToMove.getLocation().y + y_schritt);
System.out.println("SetLoc");
Thread.sleep(10);
}
catch (InterruptedException ex)
{
StatusLog("InterruptedException");
}
}
System.out.println("invokeLater");
p_lblToMove.setLocation(p_lblToMove.getLocation().x + x_offset, p_lblToMove.getLocation().y + y_offset);
}
});
MoveThread.start();
try {
System.out.println("BeforeJoin");
MoveThread.join();
System.out.println("AfterJoin");
System.out.println("------------------");
} catch (InterruptedException ex) {
Logger.getLogger(Spielfeld.class.getName()).log(Level.SEVERE, null, ex);
}
Swing is a single thread environment, meaning that you should not performing any long running or blocking operations from within the context of the Event Dispatching Thread, equally, you Swing is also not thread safe, meaning that you should only update the UI from within the context of the Event Dispatching Thread.
See Concurrency in Swing for more details.
Depending on what you're trying to achieve you could use a SwingWorker, see Worker Threads and SwingWorker for more details, or a Swing Timer, see How to use Swing Timers for more details
Also remember, Swing relies on layout managers to do much of the core work when it comes to positioning and sizing components, you might find that you are fighting the layout mangers which could cause unexpected results
Of course, you could always have a look at The Universal Tween Engine and Sliding layout or Java: Moving jLabel twice using Timer
Related
Hey i just need a question answered...
How would i make the following code not freeze my whole JFrame?
try {
Thread.sleep(Integer.parseInt(delayField.getText()) * 1000);
System.out.println("Hello!");
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
use a different thread to perform this task. If you do this in the main UI thread then it will freeze.. For example you can do following
new Thread() {
#Override
public void run() {
try {
Thread.sleep(Integer.parseInt(delayField.getText()) * 1000);
System.out.println("Hello!");
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}.start();
UPDATE
AFter wise suggestions of Robin and Marko I am updating the answer with a better solution.
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
System.out.println("Hello!");
}
};
javax.swing.Timer t = new javax.swing.Timer(Integer.parseInt(delayField.getText()) * 1000, taskPerformer);
t.setRepeats(false);
t.start();
Whenever you are about to use Thread.sleep in your GUI code, stop yourself and think of Swing Timer, which is the right tool for the job. Schedule the task you need to perform with a delay.
Using another thread for this is not the best advice: it wastes a heavy system resource (a thread) to do absolutely nothing but wait.
This is not the correct way to use threads in java . You should use swingutilities.invokelater
swing utils invoke later
You don't want to execute this on the UI (or event dispatch thread) thread. Rather in a separate thread. Otherwise (as you've seen) you'll block the UI.
It's a good practice to perform time-consuming operations on a separate thread, and make use of SwingUtilities.invokeLater() if those threads need to perform some subsequent UI action (e.g. in the above display "Hello" in the UI)
Hey i just need a question answered...
How would i make the following code not freeze my whole JFrame?
try {
Thread.sleep(Integer.parseInt(delayField.getText()) * 1000);
System.out.println("Hello!");
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
use a different thread to perform this task. If you do this in the main UI thread then it will freeze.. For example you can do following
new Thread() {
#Override
public void run() {
try {
Thread.sleep(Integer.parseInt(delayField.getText()) * 1000);
System.out.println("Hello!");
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}.start();
UPDATE
AFter wise suggestions of Robin and Marko I am updating the answer with a better solution.
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
System.out.println("Hello!");
}
};
javax.swing.Timer t = new javax.swing.Timer(Integer.parseInt(delayField.getText()) * 1000, taskPerformer);
t.setRepeats(false);
t.start();
Whenever you are about to use Thread.sleep in your GUI code, stop yourself and think of Swing Timer, which is the right tool for the job. Schedule the task you need to perform with a delay.
Using another thread for this is not the best advice: it wastes a heavy system resource (a thread) to do absolutely nothing but wait.
This is not the correct way to use threads in java . You should use swingutilities.invokelater
swing utils invoke later
You don't want to execute this on the UI (or event dispatch thread) thread. Rather in a separate thread. Otherwise (as you've seen) you'll block the UI.
It's a good practice to perform time-consuming operations on a separate thread, and make use of SwingUtilities.invokeLater() if those threads need to perform some subsequent UI action (e.g. in the above display "Hello" in the UI)
I'm writing an application that adds cards (JPanels) to a CardLayout during runtime. The problem is that some components on the card loads faster than others, making it appear glitchy and not properly rendered before it's displayed.
I want it to be ready when shown for the first time.
I have solved the issue temporary by a loading screen, which makes the thread sleep for 1500 ms. Is there a more exakt way to know if everything on the panel is loaded?
private void showLoadingScreen() {
final Component glassPane = getGlassPane();
setGlassPane(loadingPanel);
loadingPanel.setVisible(true);
Thread thread = new Thread() {
public void run() {
try {;
Thread.sleep(1500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
setGlassPane(glassPane);
}
};
thread.start();
}
Do all your file loading and data manipulation in a background thread that is created using a SwingWorker. Then before executing the SwingWorker, add a PropertyChangeListener. When the PropertyChangeEvents newValue is SwingWorker.StateValue.DONE, then you know all background work is done and you can display your GUI.
Please have a look at the Concurrency in Swing tutorial, and for an example, please have a look at this answer to a similar question.
Hey i just need a question answered...
How would i make the following code not freeze my whole JFrame?
try {
Thread.sleep(Integer.parseInt(delayField.getText()) * 1000);
System.out.println("Hello!");
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
use a different thread to perform this task. If you do this in the main UI thread then it will freeze.. For example you can do following
new Thread() {
#Override
public void run() {
try {
Thread.sleep(Integer.parseInt(delayField.getText()) * 1000);
System.out.println("Hello!");
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}.start();
UPDATE
AFter wise suggestions of Robin and Marko I am updating the answer with a better solution.
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
System.out.println("Hello!");
}
};
javax.swing.Timer t = new javax.swing.Timer(Integer.parseInt(delayField.getText()) * 1000, taskPerformer);
t.setRepeats(false);
t.start();
Whenever you are about to use Thread.sleep in your GUI code, stop yourself and think of Swing Timer, which is the right tool for the job. Schedule the task you need to perform with a delay.
Using another thread for this is not the best advice: it wastes a heavy system resource (a thread) to do absolutely nothing but wait.
This is not the correct way to use threads in java . You should use swingutilities.invokelater
swing utils invoke later
You don't want to execute this on the UI (or event dispatch thread) thread. Rather in a separate thread. Otherwise (as you've seen) you'll block the UI.
It's a good practice to perform time-consuming operations on a separate thread, and make use of SwingUtilities.invokeLater() if those threads need to perform some subsequent UI action (e.g. in the above display "Hello" in the UI)
I'm making a simple game in Java using swing and am having problems with my GUI freezing up sporadically (due to threading issues most probably) after a button press that is supposed to trigger a switch in JPanels.
I posted a related thread here, which has more details about the actual code I'm currently using (although I did update the countdown and get that working fine). From answers to that thread, it seems like usingSwingUtilities.invokeLater() or invokeAndWait() might be what I need to solve the problem, but I'm not sure where in my code it is necessary or exactly how to implement it.
I don't know that much about threading and could use any help (preferably somewhat detailed and with some sample code) that I can get. Let me know if any further details would be useful.
See: Tutorial: Concurrency in Swing
Generally speaking, the Event Dispatch Thread is a single thread, chugging through the event queue, processing one at a time.
SwingUtilities.invokeLater(..)
puts a Runnable on this queue. So it will be processed by the EDT when the EDT finishes everything on the queue before it (This is why sleeping on the queue blocks other events like repainting). It's relatively unusual to call invokeLater(..) from the EDT itself, though there are situations where it is useful (usually as a hack). I don't think I have had a legitimate use for SwingUtilities.invokeAndWait(..) in the last 6 years. Maybe once.
javax.swing.Timer can be configured to fire once or periodically. When it fires, it puts an event on the EDT queue. If you have computationally-intensive processing that need to be done, consider using javax.swing.SwingWorker to do the computation on another thread, and give you back the result in a thread-safe manner (this is also comparatively rare).
A good point to look is the docs. In your case, this explains how SwingUtilities.invokeLater() works and where to use it:
Causes doRun.run() to be executed asynchronously on the AWT event
dispatching thread. This method should be used when an application
thread needs to update the GUI.
So, in your actions that modifies the GUI you must use the invokeLater method to assure that the GUI wont freeze.
Another good resource is the Java tutorials. They cover concurrency in Swing.
I have create a WorkerThread class which take care of Threads and GUI current/main thread . i have put my GUI application in construct() method of WorkerThread when an event fire to start XXXServer then all threads are activate and GUI work smoothlly wihout freeze. have a look.
/**
* Action Event
*
* #see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
public void actionPerformed(ActionEvent ae) {
log.info("actionPerformed begin..." + ae.getActionCommand());
try {
if (ae.getActionCommand().equals(btnStart.getText())) {
final int portNumber = 9990;
try {
WorkerThread workerThread = new WorkerThread(){
public Object construct(){
log.info("Initializing the XXXServer ...");
// initializing the Socket Server
try {
XXXServer xxxServer = new XXXServer(portNumber);
xxxServer.start();
btnStart.setEnabled(false);
} catch (IOException e) {
// TODO Auto-generated catch block
log.info("actionPerformed() Start button ERROR IOEXCEPTION..." + e.getMessage());
e.printStackTrace();
}
return null;
}
};workerThread.start();
} catch (Exception e) {
log.info("actionPerformed() Start button ERROR..." + e.getMessage());
e.printStackTrace();
}
} else if (ae.getActionCommand().equals(btnStop.getText())) {
log.info("Exit..." + btnStop.getText());
closeWindow();
}
} catch (Exception e) {
log
.info("Error in ServerGUI actionPerformed==="
+ e.getMessage());
}
}
In order to invoke an action in the existing WorkerThread, one would intuitively send a user defined event using SwingUtilities.invokeLater() to a JFrame's actionPerformed() method as
class TestFrame extends JFrame implements ActionListener
{
...
private class Performer implements Runnable
{
ActionEvent event;
Performer(ActionEvent event)
{
this.event = event;
}
#Override
public void run()
{
actionPerformed(event);
}
}
synchronized protected void invokeLater(ActionEvent event)
{
SwingUtilities.invokeLater(new Performer(event));
}
public void actionPerformed(ActionEvent event)
{
...
}
}
Now, TestFrame.invokeLater() called in any Thread will be processed in TestFrame.actionPerformed() in existing WorkerThread .