Java Forum / GUI / February 2005
Delaying repainting
carlg@libertybasic.com - 08 Feb 2005 21:04 GMT Hey!
I have a routine that makes a bunch of changes to a JTree, and it takes a few seconds. The effect is rather distracting, with the tree dancing about. Is there any way to turn off the repainting until the changes are all done, and then repaint in one shot?
Thanks,
-Carl Gundel, author of Liberty BASIC http://www.libertybasic.com
Chris Smith - 08 Feb 2005 21:18 GMT > Hey! > > I have a routine that makes a bunch of changes to a JTree, and it takes > a few seconds. The effect is rather distracting, with the tree dancing > about. Is there any way to turn off the repainting until the changes > are all done, and then repaint in one shot? This should be happening without any effort on your part. The only way you'd see the behavior you describe would be if repaint events are being delivered in between the modifications to the tree. That would only happen if you modify the tree in small increments (i.e., in response to a timer event) or in a separate thread. If you're making modifications to the tree model from a non-AWT thread, then you need to read up on Swing multithreading requirements, and learn that you shouldn't do this.
 Signature www.designacourse.com The Easiest Way To Train Anyone... Anywhere.
Chris Smith - Lead Software Developer/Technical Trainer MindIQ Corporation
carlg@libertybasic.com - 09 Feb 2005 16:17 GMT > This should be happening without any effort on your part. The only way > you'd see the behavior you describe would be if repaint events are being [quoted text clipped - 3 lines] > to the tree model from a non-AWT thread, then you need to read up on > Swing multithreading requirements, and learn that you shouldn't do this. Well, that really has got nothing to do with it. If I have several incoming events that cause the tree to be modified, I'd like to wait until several changes have been made. Then once I pass some level of inactivity (say a second or two) or a default timeout, I'd like to draw the whole thing in one shot.
Isn't there any general way to defer updating of a Swing component?
-Carl
Thomas Weidenfeller - 09 Feb 2005 16:41 GMT > Well, that really has got nothing to do with it. If I have several > incoming events that cause the tree to be modified, I'd like to wait [quoted text clipped - 3 lines] > > Isn't there any general way to defer updating of a Swing component? Just defer the firing of the update/change/etc. event notifications from the model to the tree (you are doing all your changes via a model, aren't you?). Do all your changes without firing the events, then once you are done fire one events (or a small set of events), indicating the changes you have done.
In order to do so you either need to implement your own model (or subclass the usual suspects and add your changes to defer event firing), or circumvent the model by directly working with the TreeNodes.
Actually Q6.2.1 of the FAQ describes the reverse of what you want (not messing with TreeNodes, because they don't fire events), but the final conclusion is the same: Get your event notification right.
/Thomas
 Signature The comp.lang.java.gui FAQ: ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq
carlg@libertybasic.com - 09 Feb 2005 22:27 GMT > > Well, that really has got nothing to do with it. If I have several > > incoming events that cause the tree to be modified, I'd like to wait [quoted text clipped - 13 lines] > subclass the usual suspects and add your changes to defer event firing), > or circumvent the model by directly working with the TreeNodes. Yes, I am making all changes through the tree model. I'll look into what you're suggesting. Thanks.
> Actually Q6.2.1 of the FAQ describes the reverse of what you want (not > messing with TreeNodes, because they don't fire events), but the final > conclusion is the same: Get your event notification right. My event notification is apparently being done by the book. Swing needs to have a mechanism for deferring repainting IMHO.
Thanks again,
-Carl
John McGrath - 11 Feb 2005 02:18 GMT > Just defer the firing of the update/change/etc. event notifications from > the model to the tree (you are doing all your changes via a model, > aren't you?). Do all your changes without firing the events, then once > you are done fire one events (or a small set of events), indicating the > changes you have done. I think there might be problems with this approach. The JTree updates its state both in response to events from the model and in response to external events. It also queries the model for its current state in response to those events. Blocking the events only from the model could result in inconsistencies.
For example, imagine that the events from the tree model are being blocked and a tree node is removed. While the events are still being blocked, a mouse movement triggers a tooltip. The Jtree would then query the tree model for information about the deleted node, which could cause problems.
One approach that would work would be to hide the JTree behind a component that looked just like it. You could do this with a component that captures an image from the JTree (or any component) and displays that image.
Another approach would be to not update the model until you actually want the updates to show. If the updates are all performed in the event handler for a single event, the user would not see multiple updates occurring.
 Signature Regards,
John McGrath
Thomas Weidenfeller - 11 Feb 2005 12:30 GMT > I think there might be problems with this approach. > The JTree updates its > state both in response to events from the model and in response to > external events. It also queries the model for its current state in > response to those events. Blocking the events only from the model could > result in inconsistencies. You are just describing the typical Swing threading problems, nothing new here:
(a) If the model is updated from within the EDT, your scenario can't happen, because no other event is processed while the update code runs.
(b) If you want to update the model from outside the EDT, than that problem is also not new. Whether you change one node, or a bunch of nodes, or whatever, you always have to ensure proper synchronization.
If you work hard, you can of course mess up scenario (a) and (b). You can mess up (a) if you decide to split your update into separate steps which you each invoke separately via separate invokeLater() calls, and if these individual steps are not atomic with regards to the model's consistency. You can mess up (b) by simply messing up the locking.
All this is just standard AWT and Swing behavior and not specific to the particular scenario. Not firing events from the model to the JTree has nothing to do with this. Not firing the events should just ensure that the JTree is not updated to often or unnecessarily while you still rearrange the data.
/Thomas
 Signature The comp.lang.java.gui FAQ: ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq
John McGrath - 14 Feb 2005 10:31 GMT > (a) If the model is updated from within the EDT, your scenario can't > happen, because no other event is processed while the update code runs. If the model is updated multiple times in the processing of one event, then the problem would not occur - the user would not see the tree "dancing". However, if the model is being updated during the processing of multiple events within the event thread, and the events generated by those updates were deferred, that would cause the type of inconsistencies I spoke about.
> (b) If you want to update the model from outside the EDT, than that > problem is also not new. Whether you change one node, or a bunch of > nodes, or whatever, you always have to ensure proper synchronization. It is possible to update the model from outside the event thread, however I think that should be avoided if at all possible. I chose that route on my first large Swing application, and I regretted it.
I think a much better approach is to update the model for Swing components in the event thread. If background processes need to perform updates, then use a "split model". The processes work on one data structure that is not seen by UI components, and then the model for the UI components is updated from that data structure in the event thread. I have not come across a situation where this approach did not work well.
> You can mess up (b) by simply messing up the locking. Messing up the locking is not the only potential problem. You also have to deal with the view being out of synch with the model.
The view interacts with the model in two different ways: it receives event notifications telling it that the state of the model has changed, and it queries the model about its current state. If the model is updated from within the event thread, then the event notification occurs immediately after the state is changed. If the model is updated from another thread, then the notification must occur on the event thread, so there is a lag between the model change and the notification.
Since view components maintain state that depends on the model state, this will introduce inconsistencies. As a result, the view can end up making nonsensical queries of the model, such as asking for a non-existent node. While it is possible to bullet-proof your model to deal with such requests, thorough testing can be difficult, since which inconsistencies show up is highly dependent on timing.
> > > Just defer the firing of the update/change/etc. event notifications > > > from the model to the tree
> You are just describing the typical Swing threading problems, nothing > new here: In the case where the model is being updated in the event thread, and event notification is deferred, it would introduce the same problems that you have when updating the model outside of the event thread.
 Signature Regards,
John McGrath
Bill Tschumy - 09 Feb 2005 22:49 GMT > Hey! > [quoted text clipped - 7 lines] > -Carl Gundel, author of Liberty BASIC > http://www.libertybasic.com One possibility is to make the GlassPane visible while you are making the series of changes. After the last change, or after some time period has elapsed, hide the GlassPane. Not sure if you then need to issue a repaint request for the window (it may happen automatically).
 Signature Bill Tschumy Otherwise -- Austin, TX http://www.otherwise.com
John McGrath - 11 Feb 2005 02:37 GMT > I have a routine that makes a bunch of changes to a JTree, and it takes > a few seconds. The effect is rather distracting, with the tree dancing > about. I was just thinking about this, and I am beginning to think that something must be wrong with your application. If you have a "routine" that performs multiple updates, then there are two possibilities:
One is that the code is being executed in the event thread, in which case you should not see the effects of the updates until the routine completes.
The other is that you are updating the tree model in a thread other than the event thread, in which case your program has a problem. If you are doing this, it may appear to work fine, but this is unsafe and your program could fail somewhere down the road.
Or maybe I am misunderstanding what you are doing. If so, can you explain how this "routine" works in a little more detail?
 Signature Regards,
John McGrath
carlg@libertybasic.com - 11 Feb 2005 17:04 GMT > > I have a routine that makes a bunch of changes to a JTree, and it takes > > a few seconds. The effect is rather distracting, with the tree dancing [quoted text clipped - 14 lines] > Or maybe I am misunderstanding what you are doing. If so, can you explain > how this "routine" works in a little more detail? This is a client/server application. More than one client can cause the server to fire change events. This is just one of the things that can make the JTree "noisy". There is nothing wrong with the application. The JTree is doing what it is designed to do. I am just looking for some refinement on this behavior.
Thanks all,
-Carl
John McGrath - 14 Feb 2005 10:31 GMT > This is a client/server application. More than one client can cause > the server to fire change events. So the model resides on a remote system? Do you have a local model that is used to service the UI components, or does the model implementation query the remote system for ?
Is the model for your UI components remote? In other words, does the code query the server in order to retrieve the tree nodes and other information that the tree model provides?
Or do you have a local model that is updated in response to events from the server? If you do not have a local model, then you might want to consider creating one. With a remote model, problems on the server will cause the UI to freeze up.
Also, if you use a local model, then your "dancing" problem is somewhat easily solved: Rather than try to defer the events between the model and the UI components, defer the events between the server and the local model.
Here is an article that discusses this approach:
http://java.sun.com/products/jfc/tsc/articles/threads/threads3.html
 Signature Regards,
John McGrath
John McGrath - 14 Feb 2005 10:35 GMT Ooops. Please ignore the first paragraph. I meant to delete that:
> So the model resides on a remote system? Do you have a local model that > is used to service the UI components, or does the model implementation > query the remote system for ?
 Signature Regards,
John McGrath
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|