Background:
From the documentation, the method SwingUtilities.updateComponentTreeUI()
ask to each component in the tree (What tree?) to update their own UI properties calling the method updateUI()
.
SwingUtilities.updateComponentTreeUI()
is strictly recommended to be called after we set the LAF, calling the method: UIManager.setLookAndFeel(LAFClassName)
, otherwise the LAF theme could not be applied to some components and, worst, some components could not be redesigned (and some exceptions could be thrown?).
I am new to this kind of things and I discovered the method SwingUtilities.updateComponentTreeUI()
after the discover of the more suggestive UIManager.setLookAndFeel(LAFClassName)
method.
Before discovering SwingUtilities.updateComponentTreeUI()
I had been having some problems/Exceptions/NullPointerExceptions, and the truth is that I really wasn't understanding the reason of them until I didn't discover the SwingUtilities.updateComponentTreeUI()
method, which made me understand that some components in the tree could not be updated to the new LAF.
Concrete/real problem:
For instance, if I have a
subJFrame
(instantiated dynamically or triggered by an ActionEvent (click) in the
mainJFrame
), where I set the look and feels properties, and then I call SwingUtilitiesupdateComponentTreeUI()
passing to it a reference to the mainJFrame
:
SwingUtilities.updateComponentTreeUI(mainJFrame)
,
is this last one going to update all its sub-components/subJFrames (and hence updates the subJFrame
where I set the LAF) ?
This is not a trivial question (also keeping in my mind what the documentation says), because I call the UIManager.setLookAndFeel(LAFClassName)
method in the subJFrame
(what actually this call does?) and then I call SwingUtilities.updateComponentTreeUI()
method passing to it a reference to the mainJFrame
, so what LAF theme is going to be applied to all the sub-components of the mainJFrame
? And if some of the sub-components/subJFrames haven't been initialized yet?
You never need to call updateComponentTreeUI
if you only set the look and feel before creating components.
If you change the look and feel after having already created components then you need to call the updateUI()
method on every existing component. This is what updateComponentTreeUI
assists with: it calls updateUI()
on the component, as well as all the components it contains (and all the components that they contain; this is what it means by "tree").
If I have a
subJFrame
where I set the look and feel, and then I callSwingUtilities.updateComponentTreeUI()
passing to it a reference to themainJFrame
: is this going to update all its sub-components/subJFrames (and hence updates the subJFrame where I set the LAF)?
If by subJFrame
you mean a window that is directly contained within the other (a JInternalFrame
) then yes. If you mean a frame which was merely opened from the other frame, but is a separate top-level window, then no, it won't update it, because it is not contained within the component that is being updated.
This is the loop I use for updating all top-level windows after changing the look and feel:
for (Window w : Window.getWindows()) {
SwingUtilities.updateComponentTreeUI(w);
if (w.isDisplayable() &&
(w instanceof Frame ? !((Frame)w).isResizable() :
w instanceof Dialog ? !((Dialog)w).isResizable() :
true)) w.pack();
}
That loop won't catch any components that are not currently attached to windows. For example, this can include JFileChooser
s, if you keep instances of those in variables when they're not actively being displayed, in which case you will need to call updateComponentTreeUI separately on those.