Why does my program ignore repaint() method? [duplicate] - java

Here is a snippet
kit.insertHTML(doc, doc.getLength(), "Hello", 0, 0, null);
try{
Thread.sleep(1000);
}catch(Exception e){}
I am using HTMLEditorKit() and HTMLDocument() as a textbox.
The textbox should show "Hello" then wait one second however, when I try this, It waits one second then puts the word "Hello" which is not what I want.
I am not sure why this happens because I put this in the logical order. If anyone can help me with this, that would be great.
EDIT:
Does anyone know an alternative, so I can use the "delay" sort of effect?

Don't ever call Thread.sleep(...) from within the Swing event thread as this will put the event thread itself to sleep. Since this thread is responsible for all Swing painting and user interaction, this will put your application to sleep.
If all you want is a delay in the display, then consider use of a Swing Timer.
If on the other hand your event thread is being compromised by a long-running task, then do the task in the background, using a SwingWorker (as suggested by Guillaume 1+ to him).

You are calling sleep on the EDT (Event Dispatching Thread). You should avoid this situation as indeed, it freezes the UI.
To avoid this situation, use a SwingWorker instead or as suggested by HFOE, use a Swing Timer

Thread.sleep is a long running task. When you a running such a task in the EDT it blocks all repaint requests from being executed. All repaint requests which are pending and which were sent during the sleep phase are queued for future processing.
As a result when the EDT comes out of the sleep phase it coalesce all such repaint request (if coalescing is enabled which is the default property) into a single repaint which gets executed. If coalescing is not enabled then all queued request are executed serially without any time gap in between. As a result it seems that the UI did not update.
To correct the situation use a SwingTimer which triggers periodically after specific intervals of time, or a SwingWorker.

Related

Why creating a class and calling the class function suspend any visual change [duplicate]

Here is a snippet
kit.insertHTML(doc, doc.getLength(), "Hello", 0, 0, null);
try{
Thread.sleep(1000);
}catch(Exception e){}
I am using HTMLEditorKit() and HTMLDocument() as a textbox.
The textbox should show "Hello" then wait one second however, when I try this, It waits one second then puts the word "Hello" which is not what I want.
I am not sure why this happens because I put this in the logical order. If anyone can help me with this, that would be great.
EDIT:
Does anyone know an alternative, so I can use the "delay" sort of effect?
Don't ever call Thread.sleep(...) from within the Swing event thread as this will put the event thread itself to sleep. Since this thread is responsible for all Swing painting and user interaction, this will put your application to sleep.
If all you want is a delay in the display, then consider use of a Swing Timer.
If on the other hand your event thread is being compromised by a long-running task, then do the task in the background, using a SwingWorker (as suggested by Guillaume 1+ to him).
You are calling sleep on the EDT (Event Dispatching Thread). You should avoid this situation as indeed, it freezes the UI.
To avoid this situation, use a SwingWorker instead or as suggested by HFOE, use a Swing Timer
Thread.sleep is a long running task. When you a running such a task in the EDT it blocks all repaint requests from being executed. All repaint requests which are pending and which were sent during the sleep phase are queued for future processing.
As a result when the EDT comes out of the sleep phase it coalesce all such repaint request (if coalescing is enabled which is the default property) into a single repaint which gets executed. If coalescing is not enabled then all queued request are executed serially without any time gap in between. As a result it seems that the UI did not update.
To correct the situation use a SwingTimer which triggers periodically after specific intervals of time, or a SwingWorker.

EDT in Java, how does it work, does it behave like normal thread (single or mutli)?

this is a beginner question:
I am working on a small chat program that use TCP to deliver messages, and I have a simple GUI to display it, I have finished the program, but the EDT has confused me a lot...
does EDT behave like it "extends Thread"? I imagine it is a single thread since I will need worker thread to process the heavy logic, but apparently I can not do Thread.sleep/yield (I have a while loop that constantly reading message from the outputstream and append to the jTextArea, running in main Thread, I tried to terminate the while loop by set a false flag and then yield to main Thread, did not work.)
I am not so sure about how listener works, if I have to write it...I will probably start a thread for each listener, as soon as I hear something I will process it...but this is definitely wrong because it will make EDT a multithread ( a lot of ears ) but singlethread during the process ( only 1 brain )
This must be me lacking knowledge!! because in my head I just can not figure out how to fire an event... you pressed a button and java suddenly knows? I must missed something.
My first time post a question, hope it is clear
The Event Dispatching Thread is a Thread like any other Thread in Java.
It is responsible for dispatching all events and repaint requests (and few other things, like running synchronized Runnable). Any action you take that blocks the EDT will stop it from processing these events, making it look like your application has hung ... because basically it has.
All interactions with any UI component MUST be executed within the context of the EDT. That means you should never try and create or update any UI component from any Thread other then the EDT.
If you need to do any actions that are blocking or time consuming, you should use another thread. SwingWorker is an excellent place to start.
Adding listeners to component will not create more threads. The EDT will post event notifications back to the listeners (this is an incredibly shortened explanation, but the concept is sound), this is one of the reasons why you should never block the EDT.
How events are raised depends on the component. Mouse and keyboard events for example, will be posted to the Event Queue by a native portion of code dependent on the OS/implementation (as I understand it, coming from the ToolKit, but I could be wrong).
actionPerformed events raised by JButtons may be executed directly against the listener (not dispatched via the Event Queue), but within the EDT. This are raised by any number of events, but typically caused by mouse clicks and special key events. The JButton is notified of these because it registers itself with the Event Queue.
While getting an understanding of the workings is a good goal, you need to ask yourself, does it matter (in the short term)? Do you know how electricity gets from the light switch to the light? Or do you only care that it does?
Understand the rules required to use it (don't stick sharp objects into the power points) and let the understanding come as you become more confident.

Get a notification in Swing when a thread completes / is finished

It seems I miss a certain point in Java and Swing. The issue is as follows:
I have a swing GUI with a Start / Stop button (And some more)
It starts the function (What is set up as a thread in this case), Thread starts, it works, Swing GUI is fully operational and does all the other things it is made for, e.g. modifying parameters for the worker thread.
Of course, sending an interrupt to ask the thread to stop on users request is in and functions. So far so good.
But I did not found a way that Swing GUI notices the thread stopped on its own:
If I ignore it, it confuses the user.
I of course put a loop in, where Swing GUI regularly asks if Thread.isAlive (And sleeps some time to ask again), but this loop completely blocks Swing GUI.
Ideally, I would like to get a notification or an event that the thread has stopped.
Just like all the other events, Swing processes:-) .
What is the proper way to set it up?
Have a look at the SwingWorker. It is designed to perform tasks on the background as the result of a Swing event such a button press. It has hooks to listen for when the task finishes.
use a boolean flag 'done' private field. initialize done=false; when your thread run() method is complete set done=true inside thread run() method.
monitoring the value of the flag 'done' will tell you when your thread has finished.

Using a timer to start a SwingWorker?

The task I need to perform involves requesting some data from an external server, performing some (fairly lengthy) processing on the data, and then updating the GUI with the results of the processing. Because the server might be unresponsive, the task is well suited to a SwingWorker: the doInBackground() method gets the results, and then the done method updates the GUI.
I need this to happen once every few seconds. I know I can just use a while loop and Thread.sleep, and create a new SwingWorker after each sleep. But everything I've read frowns upon using loops and sleep. I'd like to use a timer but:
Using a swing timer seems counterproductive; since they run on the EDT, I would essentially have no reason to use SwingWorker's doInBackground method. If the server were not responsive, the GUI would be unresponsive.
Using a java.util.Timer seems a bit wasteful: it seems to create a background thread for the TimerTask(), and since I am just creating a SwingWorker to do the actual work, I'm essentially creating a background thread that creates another background thread.
Can anybody tell me what's the best solution? I'd like to stick with SwingWorker since it seems ideally suited to the task, but I would like to avoid using a while loop if I can help it.
Thanks
You could use a ScheduledExecutorService:
scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
// get a scheduled executor service with one thread
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
// schedule the worker at an intervall of 5 seconds
scheduler.scheduleAtFixedRate(myWorker, 0, 5, TimeUnit.SECONDS);
I don't see why you couldn't use a Swing Timer to start a Swing Worker. What have you tried?
I think you're on the right track with SwingWorker. Now you need to look at its publish and process methods. As your processing progresses, you publish() an object from the background thread then the process() method is called on the Swing(EDT) thread so you can update the gui.
This way there aren't a bunch of timers and other threads to coordinate.
The javadocs have a straightforward example with prime numbers:
http://download.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html
How large is the set of data you are retrieving? If it is fairly small I would completely detach the task of fetching/processing and displaying.
Use some sort of in memory cache to hold the most recently processed set of data.
Use a javax.swing.Timer to update the GUI with the cached data.
Use a java.util.Timer to fetch the data from the database, process it and update the cache.
Be careful of synchronisation issues between the two times on your cache. You don't want your swing timer grabbing data at the same time as the other timer is updating it.

Thread.sleep and repainting

I have a panel that displays text. I want the panel to change its text and then have the application pause before anything else happens. I'm using Thread.sleep(1000). For some reason, though, the application doesn't finish painting the panel before Thread.sleep gets called (the text doesn't get changed). I also tried this:
board.invalidate();
board.setLeftMessage("Not");
board.setRightMessage("Here");
board.revalidate();
Date current = new Date();
long timeNow = current.getTime();
Date newDate = new Date(timeNow + 1000);
while (current.before(newDate))
current = new Date();
but no luck there either. Anyone have a suggestion?
Thanks so much.
You are blocking the AWT Event Dispatch Thread (EDT). The EDT handle repainting and input events, so your code need not be multithreaded (which would be effectively impossible). Use javax.swing.Timer to send an event later on the EDT. (Do not confuse javax.swing.Timer with java.util.Timer!)
Take a look at javax.swing.Timer - I think this is what you'll need to accomplish this.
EDIT #1: The Sun\Oracle documentation actually suggests using Swing Timers from here.
In general, we recommend using Swing
timers rather than general-purpose
timers for GUI-related tasks because
Swing timers all share the same,
pre-existing timer thread and the
GUI-related task automatically
executes on the event-dispatch thread.
However, you might use a
general-purpose timer if you don't
plan on touching the GUI from the
timer, or need to perform lengthy
processing.
EDIT #2: It looks like there are some good basic tutorials here.
EDIT #3: Removed suggestion of using TimerTask - in this case it would be a bad idea.
Your "long running task" needs to run in a separate Thread. Then when you want to update the GUI you need the code to run on the Event Dispatch Thread (EDT). Then you can ask the separate Thread to sleep and it won't affect the painting of the GUI.
You should be able to use a SwingWorker for this. Read the section from the Swing tutorial on Concurrency for more information.
If you don't like using the SwingWorker, then you need to create your own Thread and wrap the code that updates the GUI in a SwingUtilities.invokeLater().
You shouldn't be updating GUI components from your main thread. Use SwingUtilities.invokeLater to schedule your update on the event thread:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
board.invalidate();
board.setLeftMessage("Not");
board.setRightMessage("Here");
board.revalidate();
}
};
Thread.sleep is a long running task. When you a running such a task in the EDT it blocks all repaint requests from being executed. All repaint requests which are pending and which were sent during the sleep phase are queued for future processing.
As a result when the EDT comes out of the sleep phase it coalesce all such repaint request (if coalescing is enabled which is the default property) into a single repaint which gets executed. If coalescing is not enabled then all queued request are executed serially without any time gap in between. As a result it seems that the UI did not update.
To correct the situation use a timer which triggers periodically after specific intervals of time.

Categories

Resources