8
\$\begingroup\$

I am using JGoodies Looks to change the look and feel of the application I'm currently working on.

I've just created a JMenu with some different themes options for the user to choose.

The thing is, I want to make sure the changes affect the program instantly, on all current windows, so I did this:

@Override
public void doActionPerformed(ActionEvent event) {
    PlasticLookAndFeel lookAndFeel = new PlasticXPLookAndFeel();
    lookAndFeel.setPlasticTheme(new SkyBlue());
    try {
        UIManager.setLookAndFeel(lookAndFeel);
        for(Frame f: Frame.getFrames()) {
            SwingUtilities.updateComponentTreeUI(f);
        }
    } catch (UnsupportedLookAndFeelException e) {
        e.printStackTrace();
    }
}

It works perfectly, like magic. But I don't know if it is a good practice or not, or if there is a better or easier (if possible) way.

I didn't even know that Frame had that method. I've just tried (thanks to IntelliJ magic code completion) and it worked so easy on the first try. So maybe that's why I'm concerned about it.

Also, what is the difference between the code above and this one (as they appear to work the exact same way):

for(Window window : JFrame.getWindows()) {
    SwingUtilities.updateComponentTreeUI(window);
}

I mean, when and why should I be using Frame over JFrame, Frame over Window, or vice versa?

\$\endgroup\$
2
+50
\$\begingroup\$

Java GUIs: Swing & AWT

In standard Java there are two ways to make GUIs: Swing and AWT.

To be short, Swing is platform-independent and AWT is platform-dependent. Typically you pick either AWT or Swing and stick to it. I believe Swing is the more popular choice today as it is easier to work with.

You can tell Swing code from AWT code by the fact that Swing component classes are prefixed with a J. For example Frame is AWT and JFrame is the Swing equivalent.

The Swing components inherit from the AWT components so a JFrame is a Frame.

Windows and Frames

Now the difference between Window and Frame (and JWindow and JFrame respectively) is that a Window is a plain window without any decorations; no borders, no title bar, no window management buttons. A Frame is a Window with all these decorations. And I put emphasis on is a in the above as Frame actually inherits Window.

So the inheritance tree looks like this:

          lang.Object
              |
           awt.Component
              |
           awt.Container
              |
           awt.Window
              |
     +--------+-------+
     |                |
swing.JWindow      awt.Frame
                      |
                 swing.JFrame

To answer your question about which of the methods is better. Note that getWindows() is defined in Window and inherited by JWindow, Frame and JFrame. Calling getWindows() will get all windows, even owner-less dialogues and system windows associated with the application, regardless of if they have decorations or not. On the other hand getFrames() is defined in Frame so calling getFrames() will get all windows with decorations (frames). If your application doesn't have any frame-less windows, the two pieces of code you posted will be equivalent.

The Code

Your code is likely fine as it is wither either approach as plain Windows are kind of rare and often transient. The approach you're using is the standard one.

If you want to be absolutely sure you get every window there is and be picky about it, this is how I would write it:

for(Window window: Window.getWindows()) {
    SwingUtilities.updateComponentTreeUI(window);
}

For your reference, see the Java Docs for JWindow and JFrame and their super classes.

\$\endgroup\$
5
  • \$\begingroup\$ Pretty interesting, I knew a little bit about AWT but very superficial. Now every thing is more clarified to me. \$\endgroup\$ – Patrick Bard Jun 25 '15 at 13:58
  • \$\begingroup\$ But just some simple questions to finish: If I understood correctly calling Window.getWindows() would be exact the same as JFrame.getWindows() (or any other which inherit Window), correct? And you just wrote that way just to be more "coherent" right, or I forgot something? Another question is that, you really think there is no problem with the code? I was thinking that "it will get all windows, even owner-less dialogues and system windows associated with the application" could imply an overhead of operations, and that maybe using getFrames() would be a better approach, what you think? \$\endgroup\$ – Patrick Bard Jun 25 '15 at 14:01
  • 1
    \$\begingroup\$ @PatrickBard Yes JFrame.getWindows() is the exact same function as Window.getWindows(), you just call it using another qualifying sub-class. Yes I wanted to make it clear that the actual method I'm calling belongs to Window and that I want all windows regardless of their type. As for the overhead, write for correctness first, with that out of the way I would expect that getFrames() is implemented something like List<Frame> fs; for(Window w : getWindows()){ if(w instanceof Frame){ fs.add(w);} return fs.toArray();. So unless you actually need Frames, use getWindows(). \$\endgroup\$ – Emily L. Jun 25 '15 at 14:42
  • 1
    \$\begingroup\$ @PatrickBard In general you should prefer to use the least specialised type in your code. If you don't need the specialisations added by Frame (you don't) then simply use the base class Window.getWindows(). For example always prefer to use a List (or even Collection when order is irrelevant) as type instead of ArrayList. \$\endgroup\$ – Emily L. Jun 25 '15 at 14:46
  • \$\begingroup\$ Yes, that comparison with ArrayList make sense now, the first time I saw your code I thought that it was something similar. I generally use that way for my lists, now I'll try to do it everywhere. Thank you very much for your kind explanations :) \$\endgroup\$ – Patrick Bard Jun 25 '15 at 16:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.