How to debug needless repainting occurring within Swing
I'm having some strange issues with repainting going on in a Swing app I'm developing. I'm finding that when I set the text of a certain component (it's just a status bar text label along the very bottom of the window) an entire table in a very different area of the screen is being told to repaint. It's causing some performance issues because it seems like basically the ent开发者_如何转开发ire window is being asked to repaint every time I set the status bar text.
I've been wandering around the RepaintManager trying to figure out what's going on, and have found that my entire main JPanel is being marked as a dirty component when I try to set the label of this text. However, I'm having trouble debugging at what point that's occurring and exactly why it's occurring at all. I've tried to read up on the repainting systems, but I can't determine why it would be necessary for a non-overlapping table to repaint when some other text label is set.
I've used Swing Explorer to try to visualize the layout borders to make sure things aren't overlapping in some crazy way, and everything appears to be fine.
I'm looking for an approach to determine what sequence of calls is asking the JTable to repaint. When I add a breakpoint on its paintComponent() and walk up the stack, I end up inside the RepaintManager's paintDirtyRegions() call in which my entire main JPanel (that contains everything in the window) is sitting inside the tmpDirtyComponents variable.
Can anybody explain how my entire JPanel could get marked as dirty when I'm initially just setting a single status text label? If not, could you provide some guidance as to where to hook in to find the error?
Thanks so much for any assistance you can provide!
Whenever you change a property on a Swing component revalidate() and repaint() are invoked on the component. Setting the text can cause the preferred size of the components to change so therefore the layout manager needs to be invoked and the entire panel repainted.
I'm not sure how to get around this.
Somehow I've managed to skirt this issue by changing my layout manager. My main panel was using a GroupLayout. Since the overall GroupLayout was so simple I decided to try a BorderLayout instead, with the main window contents in a JPanel added to BorderLayout.CENTER and the status bar label at BorderLayout.PAGE_END. It fixes the weird invalidation and redrawing of the whole window when I set the status label text! Thanks to everybody for their great suggestions!
Just to add to camickr's comment, overriding isValidateRoot() for the troublesome component is the correct solution to this problem, and is usually the correct solution to solving unnecessary repaint problems.
The drawback is that if a change to your isValidateRoot component does actually require the component to change size, you will need to force a revalidation manually (myValidateRoot.getParent().invalidate() should do it).
精彩评论