JFrame#setLayout(LayoutManager) 不起作用。强制做 getContentPane().setLayout(LayoutManager)

Vin*_*igh 0 java swing jframe layout-manager contentpane

运行实例化此类的代码时:

static final class MyFrame extends JFrame {
    private CardLayout layout = new CardLayout();

    public MyFrame() {
        setLayout(layout);
        System.out.println(getLayout());
    }
}
Run Code Online (Sandbox Code Playgroud)

打印出来的结果是:

java.awt.BorderLayout[hgap=0,vgap=0]
Run Code Online (Sandbox Code Playgroud)

这是JFrame默认布局。布局没有改变。但是,如果我改变

setLayout(layout);
Run Code Online (Sandbox Code Playgroud)

getContentPane().setLayout(layout)
Run Code Online (Sandbox Code Playgroud)

getLayout() 将打印正确的布局。

MVCE:

不设置布局:

public class Main {
    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            MyFrame frame = new MyFrame();
            frame.setVisible(true);
        });
    }

    static final class MyFrame extends JFrame {
        private CardLayout layout = new CardLayout();

        public MyFrame() {
            setLayout(layout);
            System.out.println(getLayout());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

设置布局:

public class Main {
    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            MyFrame frame = new MyFrame();
            frame.setVisible(true);
        });
    }

    static final class MyFrame extends JFrame {
        private CardLayout layout = new CardLayout();

        public MyFrame() {
            getContentPane().setLayout(layout);
            System.out.println(getLayout());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Yas*_*jaj 5

我认为你在某处遗漏了一些东西。这是我的电脑上使用

setLayout(layout);
System.out.println(getContentPane().getLayout()); // CardLayout is printed
System.out.println(getLayout()); // BorderLayout is printed

getContentPane().setLayout(layout);
System.out.println(getContentPane().getLayout()); // CardLayout is printed
System.out.println(getLayout()); // BorderLayout is printed
Run Code Online (Sandbox Code Playgroud)

为什么不总是打印 CardLayout?

因为,不像JFrame#setLayout(LayoutManager)JFrame#getLayout()不会调用它的contentPane().

事实上,JFrame#getLayout()实际上是继承自Container#getLayout()which 将从LayoutManager实际组件返回实际值(在这种情况下,JFrame而不是它的contentPane())。


JFrame#setLayout

设置布局管理器。重写以有条件地将调用转发到 contentPane。有关详细信息,请参阅 RootPaneContainer。