2

When I set a look and feel through the UIManager.setLookAndFeel the frame's content changes its look and feel as expected. E.g.

public static void main(String[] args) throws Exception {
  UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");

  JFrame frame = new JFrame();
  Container contentPane = frame.getContentPane();
  contentPane.setLayout(new FlowLayout());
  contentPane.add(new JButton("Some Button"));

  frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
  frame.setSize(200, 80);
  frame.setLocationRelativeTo(null);
  frame.setVisible(true);
}

Nimbus Look and Feel Frame

But the frame is still painted using the OS default (Windows in my case).

How can I make the frame look and feel aware so that it looks like the e.g. the nimbus look and feel?

Look and feel aware frame

Usually look and feel is implemented using the ComponentUI, but a JFrame is not a JComponent so I can't implement an own ComponentUI and set it.

1. Solution

My first thought was to use an undecorated JFrame with a JInternalFrame as its main component.

public class LAFAwareJFrame extends JFrame {

  private JInternalFrame lafFrame = new JInternalFrame("", true, true, true, true);
  private JDesktopPane desktopPane = new JDesktopPane();


  public LAFAwareJFrame() {
    super.setUndecorated(true);
    desktopPane.add(lafFrame);
    lafFrame.setVisible(true);
    Container contentPane = super.getContentPane();
    contentPane.add(desktopPane);
  }

  @Override
  public void setUndecorated(boolean undecorated) {
    throw new UnsupportedOperationException("Can't change the undecorated property for a LAFAwareJFrame");
  }

  @Override
  public void setSize(int width, int height) {
    super.setSize(width, height);
    lafFrame.setSize(width, height);
  }

  @Override
  public Container getContentPane() {
    return lafFrame.getContentPane();
  }

  @Override
  public void setTitle(String title) {
    lafFrame.setTitle(title);
  }

    public static void main(String[] args) throws Exception {
      UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");

      JFrame frame = new LAFAwareJFrame();
      Container contentPane = frame.getContentPane();
      contentPane.setLayout(new FlowLayout());
      contentPane.add(new JButton("Some Button"));

      frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      frame.setSize(200, 80);
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
    }
}

But then I have a lot to do with event handling and delegation. E.g when the JInternalFrame gets moved I don't really want to move the internal frame. Instead I want to move the undecorated frame.

2. Solution

Use the JInternalFrame only as a renderer. Like a ListCellRender.


Since all solutions require a lot of work I want to ask you first if there is a better solution. E.g. a library or maybe it is already possible with standard Java and I missed something.

EDIT I tried to use setDefaultLookAndFeelDecorated but it doesn't work with nimbus and not with motif.

Community
  • 1
  • 1
René Link
  • 48,224
  • 13
  • 108
  • 140
  • Have you tried changing the [Nimbus Defaults](https://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/_nimbusDefaults.html)? – KyleKW Dec 01 '16 at 14:39
  • Checked all the installed `LookAndFeel` on a Windows JRE. Only `Metal LookAndFeel` supports decorations on the windows platform. – Stefan Dec 01 '16 at 15:00
  • On Mac OS X, `setWindowDecorationStyle()` works with both `com.apple.laf.AquaLookAndFeel` and `javax.swing.plaf.metal.MetalLookAndFeel`; more ]here](http://stackoverflow.com/a/35255215/230513). – trashgod Dec 02 '16 at 03:58

0 Answers0