Java 为什么我的框架没有调整大小?

Java 为什么我的框架没有调整大小?,java,swing,user-interface,jframe,contentpane,Java,Swing,User Interface,Jframe,Contentpane,选择状态时,框架的内容窗格将删除其组件。然后,根据您选择的状态,另一个类获取内容窗格并添加到其中。执行此操作后,框架将被压缩以相应地调整大小 我想要自由控制框架中的内容,例如能够将面板并排放置,在彼此上方,等等。。所以我真的不想使用CardLayout。(我更希望有一个面板来处理loginscreen和chat。然后,能够在该面板旁边显示另一个面板) 我在登录和聊天屏幕上使用JFrame的内容窗格,但是当我运行代码时,我得到了一个小框架(有一些大小,但几乎没有),里面是白色的 展示架 切换到聊天

选择状态时,框架的内容窗格将删除其组件。然后,根据您选择的状态,另一个类获取内容窗格并添加到其中。执行此操作后,框架将被压缩以相应地调整大小

我想要自由控制框架中的内容,例如能够将面板并排放置,在彼此上方,等等。。所以我真的不想使用CardLayout。(我更希望有一个面板来处理loginscreen和chat。然后,能够在该面板旁边显示另一个面板)

我在登录和聊天屏幕上使用JFrame的内容窗格,但是当我运行代码时,我得到了一个小框架(有一些大小,但几乎没有),里面是白色的

  • 展示架
  • 切换到聊天
  • 删除窗格中的所有内容(当前无任何内容)
  • 将组件添加到窗格中
  • 包装框架,使其能够根据窗格调整大小
  • 如果需要重新验证(不确定何时需要重新验证)
  • 请告诉我我做错了什么,也许能指引我正确的方向。 PS:没有错误

    编辑:我唯一能想到的是,由于我正在通过方法传递
    frame.getContentPane()
    ,并且方法是按值传递的,所以对
    frame.getContentPane()
    的实际引用可能没有注意到我请求的更改。但是我不知道为什么帧的内部会是白色的(就像我的JTextArea尝试渲染一样),并且帧的内部有填充,所以一定会发生一些事情

    Main.java:

    package main;
    
    import ui.Frame;
    
    public class Main {
        public static Frame frame = new Frame();
    
        public static void main(String[] args) {
            frame.show();
            frame.switchState(State.chat);
    
        }
    
        public static enum State {
            login, chat;
        }
    }
    
    Frame.java:

    package ui;
    
    import main.Main.State; 
    import javax.swing.JFrame;
    
    public class Frame {
            private Panel currentpanel; //from package ui, not AWT
            private ChatPanel chatpanel = new ChatPanel();
    
            private JFrame frame;
            public Frame() {
                frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setResizable(false);
            }
    
            public void show() {
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
    
            public void switchState(State state) {
                frame.removeAll();
    
                switch(state) {
                     case chat:
                    currentpanel = chatpanel;
                    currentpanel.addComponentsTo(frame.getContentPane());
                    break;
                }
                frame.pack();
                frame.revalidate();
            }
        }
    
    Panel.java:

    package ui;
    
    import java.awt.Container;
    
    public interface Panel {
        public void addComponentsTo(Container pane);
    }
    
    package ui;
    
    import java.awt.Container;
    import java.awt.Dimension;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    
    import javax.swing.JTextArea;
    
    public class ChatPanel implements Panel {
        private JTextArea toparea = new JTextArea();
        private JTextArea bottomarea = new JTextArea();
    
        @Override
        public void addComponentsTo(Container pane) {
            pane.setPreferredSize(new Dimension(500, 500));
            pane.setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
    
            gbc.gridy = 0;
            gbc.gridx = 0;
            gbc.ipadx = 450;
            gbc.ipady = 350;
            pane.add(toparea, gbc);
    
            gbc.gridy = 1;
            gbc.ipady = 100;
            pane.add(bottomarea);
        }
    }
    
    ChatPanel.java:

    package ui;
    
    import java.awt.Container;
    
    public interface Panel {
        public void addComponentsTo(Container pane);
    }
    
    package ui;
    
    import java.awt.Container;
    import java.awt.Dimension;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    
    import javax.swing.JTextArea;
    
    public class ChatPanel implements Panel {
        private JTextArea toparea = new JTextArea();
        private JTextArea bottomarea = new JTextArea();
    
        @Override
        public void addComponentsTo(Container pane) {
            pane.setPreferredSize(new Dimension(500, 500));
            pane.setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
    
            gbc.gridy = 0;
            gbc.gridx = 0;
            gbc.ipadx = 450;
            gbc.ipady = 350;
            pane.add(toparea, gbc);
    
            gbc.gridy = 1;
            gbc.ipady = 100;
            pane.add(bottomarea);
        }
    }
    

    我知道这会让人很沮丧

    你打过电话吗

    pack(); or repaint();
    

    我发现了问题。它正在调用
    frame.removeAll()在添加任何内容之前

    当我尝试
    if(frame.getComponents().length>0)
    时,它仍然触发了
    removeAll()
    ,但问题没有解决。看到我还没有添加任何东西,我检查了组件是什么(通过打印出对象),它是一个
    JRootPane

    在那之后,我试着打印出
    frame.getContentPane().getComponents().length
    ,结果是0

    长话短说:这就是
    开关面板(状态)
    的外观:

        public void switchState(State state) {
            if(frame.getContentPane().getComponents().length > 0)
                 frame.removeAll();
    
            switch(state) {
                 case chat:
                     currentpanel = chatpanel;
                     currentpanel.addComponentsTo(frame.getContentPane());
                     break;
            }
            frame.pack();
            frame.revalidate();
        }
    
    注意:我仍然推荐CardLayout,但是如果您坚持动态设置框架的内容窗格,那么它就在这里

    框架类

    public class SwitchingFrame extends JFrame {
    
        public static enum State {ONE, TWO}
        private PanelONE panel1 = new PanelONE();
        private PanelTWO panel2 = new PanelTWO();
    
        public SwitchingFrame() {
    
            getContentPane().setLayout(new BorderLayout());
            pack();
            setVisible(true);
        }
    
        public void switchState(State state) {
    
            setVisible(false);
            getContentPane().removeAll();
            if (state.equals(State.ONE))
                getContentPane().add(panel1, BorderLayout.CENTER);
            else
                getContentPane().add(panel2, BorderLayout.CENTER);
            pack();
            setVisible(true);
        }
    }
    
    切换的两个面板类

    public class PanelONE extends JPanel {
    
        public PanelONE() {
    
            add(new JLabel("ONE"));
        }
    }
    

    主要方法包括模拟更改面板的按钮

    public class TestSwitchingFrame {
    
        public static void main(String[] args) {
    
            final SwitchingFrame sframe = new SwitchingFrame();
    
            JFrame frame = new JFrame();
            JButton b1 = new JButton("ONE");
            b1.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    sframe.switchState(SwitchingFrame.State.ONE);
                }
            });
            JButton b2 = new JButton("TWO");
            b2.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    sframe.switchState(SwitchingFrame.State.TWO);
                }
            });
            frame.getContentPane().setLayout(new FlowLayout());
            frame.getContentPane().add(b1);
            frame.getContentPane().add(b2);
            frame.pack();
            frame.setVisible(true);
        }
    }
    

    您不需要(不应该)编写自己的接口(面板)。您的两个面板应该扩展JPanel并设置在frames内容窗格中。您的框架应该扩展JFrame,并且不需要覆盖它的
    show
    方法(让Swing为您完成)。
    switchState
    函数的具体实现最终应取决于您想要的最终结果。有类似的方法可以实现几乎相同的结果。

    Class
    LoginPanel
    未提供,代码将无法编译。调用
    frame.switchState(…)
    声称frame#switchState不可见(实际上它没有声明为公共的)。还要注意的是,你不应该在已经存在的类(如Panel和Frame)之后命名你的类,使用你自己的名称,否则会引起混淆(你的面板是一个接口,而在AWT中它是一个类)。@user1803551代码已经修复。LoginPanel已被删除,并且方法是公共的。很抱歉。为了简化这个过程,我必须删除很多代码,所以可能有一些问题与我的问题无关,但我已经解决了。小错误对,好。现在,如何对状态对象进行切换调用?开关不支持接收状态实例作为其参数。嗯?如果你说的是switch语句中的警告,它会给出警告,因为我没有默认情况。切换系统工作正常。为自己制作一个小演示,并查看打印语句。我的编译器坚持“无法打开Main.State类型的值”,并且不会运行它。我只使用if-else而不是switch。在JFrame上调用
    removeAll
    会删除其根窗格。不要使用
    JFrame\removeAll
    ,它会删除用于管理框架中的内容(和其他内容)的
    JRootPane
    ,相反,使用
    CardLayout
    或者如果必须使用
    JFrame\getContentPane().removeAll()
    。这不是一个可行的解决方案,也不是一个好的建议使用
    CardLayout
    坚持我创建两个以上的
    JPanel
    s在两者之间切换。以我的方式进行,只需使用相同的面板,即可得到相同的结果。制作
    JFrame
    s布局
    CardLayout
    的另一个缺点是我需要:1<代码>一个容器
    来容纳我的其他面板;2.用于我登录的容器;3.我聊天的容器;4.我不确定在使用
    CardLayout
    时是否可以将两个面板并排放置,我不想要两个新的JPanel对象。我想使用相同的窗格(如前所述)。我已经让它工作了,看看我发布的答案。很不幸,正如Radiodef和MadProgrammer所指出的,你这样做并不好。此外,您已经有了两个面板:您的聊天面板和登录面板是根据状态设置的两个不同组件。我知道尝试重新创建Oracle已经做过的事情(
    CardLayout
    )并不值得称赞,但它似乎比我使用
    CardLayout
    更有效。我的
    ChatPanel
    LoginPanel
    并不是真正的面板,而是更接近组件持有者。我使用的是1帧,并根据状态向该帧添加/删除现有组件。我的所有组件都被保留,不会重新初始化(如CardLayout),