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