Why doesn't setText work for JLabel component? - java

I have a JLabel which I want to change momentarily, here is the code I have written to do so:
infoLabel.setText("Added");
try {
TimeUnit.MILLISECONDS.sleep(300);
}
catch(InterruptedException ex)
{
}
infoLabel.setText("Action"); //funny part is when I comment this line it works
My default text for the label is 'Action'

Swing is a single threaded frame work, that means, if you do anything that stops this thread, then it can't respond to any new events, including paint requests.
Basically, TimeUnit.MILLISECONDS.sleep(300) is causing the Event Dispatching Thread to be put to sleep, preventing it from processing any new paint requests (amongst other things).
Instead, you should use a javax.swing.Timer
Take a look at
Concurrency in Swing
How to use Swing Timers
For more details
For example...
infoLabel.setText("Added");
Timer timer = new Timer(300, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
infoLabel.setText("Action");
}
});
timer.setRepeats(false);
timer.start();
Note, 300 milliseconds is a really short time, you might like to start with a value a little larger like 2000, which is 2 seconds ;)

You're sleeping the Swing event thread putting the entire GUI to sleep. Don't do that. Use a Swing Timer instead.

Your application is run on a single thread, so when you sleep the thread, you prevent it from making any GUI updates.

Are you sure you are doing things properly? By doing everything (including sleep) in the GUI thread, it will always be busy and never get back to Java in order to let the GUI be redrawn.
Search for EDT (Event dispatch thread) for more info. Here is one question on the subject: Processing code doesn't work (Threads, draw(), noLoop(), and loop())

Related

Thread.sleep(long mills) delaying also previous method

invalid_login_label.setVisible(false);
username_label.setVisible(false);
user_field.setVisible(false);
password_label.setVisible(false);
pass_field.setVisible(false);
access_granted_label.setVisible(true);
Thread.sleep(1000);
this.dispose();
hello world! I'm kinda newbie to java and I'm using netbeans so I have this code in my jframe. what i want is to do is after the system authenticated the user. it will remove the visibility of all fields and display "access granted" for 1000mills but it starts delaying but still not removing the visibility of fields.
Thread.sleep does just that, it causes the current thread to sleep. In this case I assume it's all done from within the context of the Event Dispatching Thread, meaning that it is unable to update the screen, as you've stopped it from processing new events, like repaint events.
Swing is a single threaded environment, that is, all interactions and modifications to the state of the UI are expected to occur from within the context of the Event Dispatching Thread. Anything which blocks this thread, such as extended I/O, long running loops or Thread.sleep will prevent the EDT from processing new events and updating the screen, making your application appear as if it has frozen...
Use a Swing Timer instead
For example...
invalid_login_label.setVisible(false);
username_label.setVisible(false);
user_field.setVisible(false);
password_label.setVisible(false);
pass_field.setVisible(false);
access_granted_label.setVisible(true);
javax.swing.Timer timer = new javax.swing.Timer(1000, new ActionListener() {
public void actionListener(ActionEvent evt) {
dispose();
}
});
timer.setRepeats(false);
timer.start();
Take a look at Concurrency in Swing and How to Use Swing Timers for more details

swing - short-time highlight of a component

I have a JTable, where a user can select a single row. If that happens, i want to "highlight" another part of the page for a short time to indicate that this is the part of the page that changed after the user interaction.
So my question is: What's the best way to achieve this? At the moment i did it by setting the background color of that panel and starting a SwingWorker which sets the Color back after a short delay. It works as intended, but is it a good idea to use a SwingWorker like that? Are there any drawbacks to that approach? How would you solve this?
Thanks in advance.
I guess a Swing Timer would be a better option as it reuses a single thread for all scheduled events and executes the event code on the main event loop. So, inside your SelectionListener code you do:
// import javax.swing.Timer;
final Color backup = componentX.getBackground();
componentX.setBackground(Color.YELLOW);
final Timer t = new Timer(700, new ActionListener() {
public void actionPerformed(ActionEvent e) {
componentX.setBackground(backup);
}
});
t.setRepeats(false);
t.start();
I recommend a swing Timer (javax.swing.Timer). (do NOT use the Timer class in Java.util)
This is where you make the timer:
Timer t = new Timer(loopTime,actionListener)//loopTime is unimportant for your use of this
t.setInitialDelay(pause)//put the length of time between starting the timer and the color being reverted to normal
t.setRepeats(false);//by default, timer class runs on loop.
t.start();//runs the timer
It probably makes sense to hold on to a reference to the timer, and then just call t.start when you need it.
You need to implement an action listener to handle the timer events. I can edit this if you don't know how to do that, but as you are already doing stuff with Swing I figure it shouldn't be a problem.

Forcing Java to refresh the Java Swing GUI

Ive coded two Computers to play each other in Reversi, however when they play each other. The board only updates after the game has finished.
From some googling around I know its has something to do the AWT Event Thread, but I still have no idea how to force the JFrame to refresh.
My function works by changing the icons and then calling revalidate and repaint.
Any pointers would be wonderful.
If you start your AI game from an actionPerformed(), it is executed in EDT thread. You should move your logic (and your sleep()'s outside of EDT thread by starting a new Thread to allow Swing to repaint UI properly and post updates to UI as following:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
myUI.update(); // repaint(), etc. according to changed states
}
});
Also consider use of javax.swing.SwingWorker, javax.swing.Timer and take a look at Concurrency in Swing.
Sounds like a threading issue - Event Thread is not being given a chance to execute. I would start with some sleep commands in the logic / action threads to give time for the UI to update.
Also, you could have an "updateUI" thread and run that on an invokeAndWait to force it to update the display. Call that after each move has been completed.
If you need to force the application to redraw, you should invoke the repaint() method on the component containing the game board. This should cause Swing to repaint the board.

GUI isn't shown while thread is in procces in JAVA

I'm making simple game with very simple thread (1 sec delay)
got problem with the thread, I have while(true) loop with the code:
try {
while (true) {
Ltimer.setText(getTimeElapsed());
Thread.currentThread();
Thread.sleep(1000); // Thread sleeping for 1 second
}
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "error with timer");
}
it simply get string every second and updates label text
when I'm trying to run it the gui freeze and I can only see the label in a black background, all buttons and bg img dissappeared. tried to fix with
setVisible()
repaint()
but got nothing..
any other options?
don' use Thread#sleep(int) during EDT, then you have issue with Concurency in Swing, if you need to delay any action use java.swing.Timer, example for EDT lack here
My guess is you are using the GUI Event Thread to do this. When you have the GUI thread tied up doing something else it cannot also be updating the screen. I suggest you run a new thread to do this.
You may not use Swing components outside of the event dispatch thread. See http://download.oracle.com/javase/6/docs/api/javax/swing/package-summary.html#threading
Use SwingUtilities.invokeLater each time your thread must change something in the UI. Or use a Swing Timer.
If this infinite loop is in fact in the EDT, then it blocks all the UI events, repaints, etc. while it's running. So you should run this loop in a separate thread.
Have a look at SwingWorker.
http://download.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html

How to keep Java Frame from waiting?

I am writing a genetic algorithm that approximates an image with a polygon. While going through the different generations, I'd like to output the progress to a JFrame. However, it seems like the JFrame waits until the GA's while loop finishes to display something. I don't believe it's a problem like repainting, since it eventually does display everything once the while loop exits. I want to GUI to update dynamically even when the while loop is running.
Here is my code:
while (some conditions) {
//do some other stuff
gui.displayPolygon(best);
gui.displayFitness(fitness);
gui.setVisible(true);
}
public void displayPolygon(Polygon poly) {
BufferedImage bpoly = ImageProcessor.createImageFromPoly(poly);
ImageProcessor.displayImage(bpoly, polyPanel);
this.setVisible(true);
}
public static void displayImage(BufferedImage bimg, JPanel panel) {
panel.removeAll();
panel.setBounds(0, 0, bimg.getWidth(), bimg.getHeight());
JImagePanel innerPanel = new JImagePanel(bimg, 25, 25);
panel.add(innerPanel);
innerPanel.setLocation(25, 25);
innerPanel.setVisible(true);
panel.setVisible(true);
}
However, it seems like the JFrame
waits until the GA's while loop
finishes to display something. I don't
believe it's a problem like repainting
Yes, if the looping code execute on the EDT then the GUI can't repaint itself until the loop finishes. The looping code should execute in its own Thread so it doesn't block the EDT.
Read the section from the Swing tutorial on Concurrency for more information.
I think your problem is that Java won't let you update the GUI from another thread than the GUI thread itself. This causes grief to everybody at some point, but fortunately a reasonably convenient workaround is provided.
The idea is to pass the code that does the updating as a Runnable to the method SwingUtilities.invokeAndWait or SwingUtilities.invokeLater. Here's an example.
To run your GA at maximum speed and exploit parallelism, I guess invokeLater would be appropriate.
EDIT: Oh wait, camickr's solution hints that you're doing something else: You're running the GA in the GUI's thread. Well, that can only do one or the other, calculate or display. So the true solution would combine both changes:
Run the GA in a separate thread (you could run it in the thread used by main() after you've instantiated the GUI); and
Use invokeLater to communicate updates to the GUI thread (which camickr calls the EDT, or Event Dispatch Thread).

Categories

Resources