1

当您选择一个状态时,框架的内容窗格会删除其组件。然后根据您选择的状态,另一个类将获取内容窗格并将其添加到其中。这样做之后,框架会被打包以相应地调整大小。

我想自由控制 Frame 中的内容,例如能够将面板并排放置,彼此重叠,等等。所以我真的不想使用 CardLayout。(我宁愿让 1 个面板同时处理登录屏幕和聊天。然后,能够在该面板旁边显示另一个面板)。

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

  1. 显示框架
  2. 切换到聊天
  3. 删除窗格上的所有内容(目前没有)
  4. 将组件添加到窗格中
  5. 打包框架,以便它可以根据窗格调整大小
  6. 如果需要重新验证(不确定何时需要重新验证)

请告诉我我做错了什么,也许可以引导我朝着正确的方向前进。PS:没有错误

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

主.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;
    }
}

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

面板.java:

package ui;

import java.awt.Container;

public interface Panel {
    public void addComponentsTo(Container pane);
}

聊天面板.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);
    }
}
4

3 回答 3

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

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

于 2014-03-25T23:50:33.877 回答
0

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

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

之后,我尝试 print out 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();
    }
于 2014-03-25T23:30:17.093 回答
0

我知道这很令人沮丧。

你试过打电话吗

pack(); or repaint();
于 2014-03-25T23:02:11.977 回答