2

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?

user14312287
  • 72
  • 2
  • 14
  • As far as I understand things, if you update the look and feel **before** rendering your component, there's no need to call `updateComponentTreeUI()`. It's only needed if you change the L&F on the fly, after the GUI has been rendered. I've never had to call this method. I've had L&F associated NPE problems, but they've all been due to my not starting my GUI properly on the Swing event thread, and corrected by fixing this. – Hovercraft Full Of Eels Jul 25 '14 at 16:07
  • But if I call the updateComononetTreeUI() I can prevent my program to crash, right? Since I wasn't understanding why my program was crashin before discovering updateComononetTreeUI().... – user14312287 Jul 25 '14 at 16:13
  • I have two questions for you: 1) Are you changing the L&F on the fly, after components have been rendered? If so, call this method. 2) Are you taking care to launch your Swing GUI on the Swing event dispatch thread (EDT), and taking care to make any calls that changes the state of a Swing component on the EDT? – Hovercraft Full Of Eels Jul 25 '14 at 16:18
  • To your first question I can asnwer that I leave the possibility to the user, after clicking on the menuitem "themes", to choose the F&L theme. The first time the user clicks on that menuitem, an instance is created, if the user clicks the menuitem "themes" twice or more, the mainJFrame is going to set it to visible, because "themes" jframe has a defaultCloseOperation(JFrame.HIDE_ON_CLOSE). – user14312287 Jul 25 '14 at 16:43
  • So to the first question I can answer yes (I think) – user14312287 Jul 25 '14 at 16:44
  • Then call the method. Incidentally, the second window should be a JDialog and not a second JFrame. – Hovercraft Full Of Eels Jul 25 '14 at 16:45

1 Answers1

5

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 call SwingUtilities.updateComponentTreeUI() passing to it a reference to the mainJFrame: 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 JFileChoosers, 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.

Boann
  • 48,794
  • 16
  • 117
  • 146
  • What do you mean by separate top-level window? As I already written in a comment, the subJFrame (where I set the themes) is created once the user clicks on the JMenuItem "Themes", and if the user exists it, if the user eventually wants again to modify the theme, the subJFrame is just going to be set to visible and not created again. So is this a separate top-level or not? – user14312287 Jul 25 '14 at 16:54
  • @bad_alloc By "top-level window" I mean one that the user can drag independently across their desktop: it is not contained inside another window and is not constrained to move strictly within the parent window's interior. Your subJFrame is a separate window if it is not a `JInternalFrame`. – Boann Jul 25 '14 at 17:02
  • If I choose the theme and then open another subJFrame, which is created on the volley (if not already created, otherwise it would be set to visible) (1) is this new subJFrame going to be affected by the call to SwingUtilities.updateComponentTreeUI(mainJFrame) called previously on the "Themes" subJFrame??? (2) Or I have explicitly to set to it the new theme, since this another subJframe wasn't created before setting the theme, (3) and if it was already created? – user14312287 Jul 25 '14 at 17:03
  • @bad_alloc You need to call updateComponentTreeUI for any components that currently exist at the time you change the look and feel. That is the only time you need to call it. If you create new components after having changed the look and feel, then the new components will already have the correct look and feel setting. – Boann Jul 25 '14 at 17:11