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

时间:2014-03-25 21:57:27

标签: java swing user-interface jframe contentpane

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

我想要自由控制框架中的什么,例如能够将面板并排放置在彼此之上,等等......所以我真的不想使用CardLayout。 (我更倾向于让1个面板处理loginscreen和chat。然后,能够显示另一个面板旁边的那个面板。)

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

  1. show frame
  2. 切换到聊天
  3. 删除窗格上的所有内容(当前没有任何内容)
  4. 将组件添加到窗格
  5. 打包框架,以便它可以相应地调整窗格大小
  6. 如果需要,
  7. 重新验证(不确定何时需要重新验证)
  8. 请告诉我我做错了什么,并指导我朝着正确的方向前进。 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);
    }
    

    ChatPanel.java:

    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);
        }
    }
    

3 个答案:

答案 0 :(得分:0)

我知道这可能非常令人沮丧。

你尝试过调用

吗?
pack(); or repaint();

答案 1 :(得分:0)

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

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

之后,我尝试打印frame.getContentPane().getComponents().length,它按预期给了我0。

长话短说:这就是switchPanel(State state)看起来的样子:

    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();
    }

答案 2 :(得分:0)

注意:我仍然推荐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 PanelONE extends JPanel {

    public PanelTWO() {

        add(new JLabel("TWO"));
    }
}

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

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);
    }
}

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