JPanel 未显示在 JFrame 中,但 JFrame 仍会更改大小
Posted
技术标签:
【中文标题】JPanel 未显示在 JFrame 中,但 JFrame 仍会更改大小【英文标题】:JPanel not showing in JFrame, but JFrame still changes size 【发布时间】:2022-01-17 13:48:24 【问题描述】:我不知道我做了什么,或者出了什么问题,但是我在最近一段时间所做的更改使我的 JPanel 完全不可见。它嵌套的 JFrame 的大小仍然会发生变化以容纳它,我仍然可以切换组合框中的内容。
无奈之下,我尝试用一个按钮替换 SnakeSettingsPanel 类的内容,但同样的事情发生了——完全不可见,但我仍然可以与之交互。我想这可能是一个计算机错误,所以我尝试重新启动,但仍然没有。当我尝试在 JPanel 外部的框架中添加一个按钮时,它工作得很好。我做错了什么?
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class SnakeSettingsPanel extends JPanel
public boolean quit = false;
public boolean play = false;
public int width = 20;
public int height = 15;
public Speed speed = Speed.SLOW;
public JTextField wField;
public JTextField hField;
public JComboBox<Speed> sField;
public static void main(String[] args)
JFrame jf = new JFrame();
jf.setTitle("Snake");
SnakeSettingsPanel settings = new SnakeSettingsPanel();
jf.add(settings);
jf.pack();
jf.setVisible(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
public SnakeSettingsPanel()
setLayout(new GridBagLayout());
// @author Create our labels.
JLabel wLabel = new JLabel("Width:");
JLabel hLabel = new JLabel("Height:");
JLabel sLabel = new JLabel("Speed:");
GridBagConstraints p = new GridBagConstraints();
p.gridx = 0;
p.gridy = 0;
p.insets = new Insets(10, 10, 10, 10);
// @author Create the buttons, and add listeners
JButton y = new JButton("Play");
JButton n = new JButton("Quit");
y.addActionListener(new PlayListener());
n.addActionListener(new QuitListener());
// @author Create text fields for height/width
wField = new JTextField(15);
wField.setText("20");
hField = new JTextField(15);
hField.setText("15");
// @author Creates a combobox for selecting speed.
Speed[] speeds = Speed.SLOW, Speed.MEDIUM, Speed.FAST;
sField = new JComboBox<Speed>(speeds);
// @author Stitch everything into the panel.
add(wLabel, p);
p.gridx = 1;
add(wField, p);
p.gridx = 0;
p.gridy = 1;
add(hLabel, p);
p.gridx = 1;
add(hField, p);
p.gridx = 0;
p.gridy = 2;
add(sLabel, p);
p.gridx = 1;
add(sField, p);
p.gridx = 0;
p.gridy = 3;
add(y, p);
p.gridx = 1;
add(n, p);
setVisible(true);
public boolean getPlay()
return play;
public boolean getQuit()
return quit;
// @author Returns all settings as a SnakeSettings object
public SnakeSettings getSettings()
return new SnakeSettings(width, height, speed);
public int getWidth()
return width;
public int getHeight()
return height;
public Speed getSpeed()
return speed;
// @author Sends out the word to start a new game.
public class PlayListener implements ActionListener
public void actionPerformed(ActionEvent e)
quit = false;
play = true;
width = Integer.parseInt(wField.getText());
height = Integer.parseInt(hField.getText());
speed = (Speed) sField.getSelectedItem();
// @author Sends out the word to shut down the program.
public class QuitListener implements ActionListener
public void actionPerformed(ActionEvent e)
quit = true;
play = false;
【问题讨论】:
【参考方案1】:让这成为您为什么应该避免将模型(您的应用程序的数据)与视图(它的显示方式)混合在一起的一课。您的SnakeSettingsPanel
目前两者兼有。
width
、height
和 speed
。
作为 View,它是一个完整的 JPanel。 JPanel 有很多字段,您应该避免直接接触这些字段。包括width
和height
,通常通过getHeight
和getWidth
访问——您将使用始终返回相同内置值20 和15 的版本覆盖它们(直到用户通过他们看不到的 UI)。
快速 修复方法是重命名您当前的 getWidth()
和 getHeight()
以避免与父 JPanel 类的内置 getWidth()
和 getHeight()
方法发生冲突。打电话给他们getMyWidth()
、getMyHeight()
,突然间一切正常。
更好的修复方法是完全删除这些字段和方法,并将您自己的模型属性存储在SnakeSettings
属性中。当用户点击播放时更新它,并在通过getSettings()
请求时返回它。为您减少代码,减少与您的父级 JPanel
类发生意外名称冲突的可能性。这看起来像:
// SnakeSettingsPanel, before
public int width = 20;
public int height = 15;
public Speed speed = Speed.SLOW;
public int getWidth() // <-- ***es with superclass
return width;
public int getHeight() // <-- ***es with superclass
return height;
public Speed getSpeed()
return speed;
public SnakeSettings getSettings()
return new SnakeSettings(width, height, speed);
// SnakeSettingsPanel, after
SnakeSettings settings = new SnakeSettings();
public SnakeSettings getSettings()
return settings;
【讨论】:
谢谢,成功了。我什至没有考虑过与 JPanel 分开的某些类会以这种方式搞砸它。你知道具体的命名约定是如何导致一个不可见的面板的吗? 面板是可见的——但它太小了,什么都没有显示(20x15,10px 插图,留给任何文本显示的空间很小)。这两个属性,宽度和高度,控制可见组件的大小。调用pack()
会使面板的布局管理器尝试为所有内容找到合适的尺寸;但是,在为您的面板找到理想的宽度和高度后,JFrame 会询问面板它想要的尺寸......面板总是回复它想要 20x15 像素的尺寸。这就是它被授予的大小。以上是关于JPanel 未显示在 JFrame 中,但 JFrame 仍会更改大小的主要内容,如果未能解决你的问题,请参考以下文章