前言
由于某些需要,需要进行 Java Swing 编程。但是在进行编程中,发现了一个很让人火大的事情,那就是给 JFrame 添加组件后,没有立即显示。你以为你程序有问题,各种查资料,发现没问题,都是这样的,然后在你骂娘的时候,你突然对窗体进行拉伸,你就发现组件又显示出来了。此时就各种冒火。那么这到底是什么鬼呢?其实就是程序语句顺序的问题,即:对 JFrame 主窗体的初始化等设置一定要放在程序最后面。
模拟场景
Main.java: [没问题的版本,仅有 3 个 JLabel]
/**
- 程序入口
- @author johnnie
*
*/
public class Main{
private static final int FRAME_WIDTH = 600;
private static final int FRAME_HEIGHT = 600;
private String title = "主界面"; // 窗体标题
private JPanel contentPanel;
/**
- 初始化控件
*/
public void initViews () {
contentPanel = new JPanel(); // 创建一个中间容器对象
contentPanel.setLayout(null);
// 得到屏幕尺寸
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int screenWidth = screenSize.width;
int screenHeight = screenSize.height;
int width = (screenWidth - FRAME_WIDTH) / 2; // x 轴位移
int height = (screenHeight - FRAME_HEIGHT) / 2; // y 轴位移
JFrame jf_main = new JFrame(this.title);
jf_main.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jf_main.setBounds(width, height, FRAME_WIDTH, FRAME_HEIGHT);
jf_main.setResizable(false); // 去掉窗体最大化
jf_main.setVisible(true);
jf_main.setContentPane(contentPanel); // 设置 JFrame 的内容面板
JLabel jl_in = new JLabel("请选择pcap文件:");
jl_in.setBounds(10, 10, 120, 35);
JLabel jl_out = new JLabel("请选择输出目录:");
jl_out.setBounds(10, 70, 120, 35);
JLabel jl_status = new JLabel("程序运行状态:");
jl_status.setBounds(10, 130, 120, 35);
contentPanel.add(jl_in);
contentPanel.add(jl_out);
contentPanel.add(jl_status);
}
public Main(String title) {
this.title = title;
}
public static void main(String[] args) {
new Main("PcapAnalyzer").initViews();;
}
}
[运行结果]
有问题的版本:[添加一个 JTextField 后,就开始傻逼了]
public void initViews () {
// ... (略,和上面一样)
JLabel jl_in = new JLabel("请选择pcap文件:");
jl_in.setBounds(10, 10, 120, 35);
JLabel jl_out = new JLabel("请选择输出目录:");
jl_out.setBounds(10, 70, 120, 35);
JLabel jl_status = new JLabel("程序运行状态:");
jl_status.setBounds(10, 130, 120, 35);
JTextField jtf = new JTextField();
jtf.setBounds(10, 10, 100, 50);
contentPanel.add(jl_in);
contentPanel.add(jl_out);
contentPanel.add(jl_status);
contentPanel.add(jtf);
}
[运行结果]
[去掉关闭窗口最大化后,拉伸窗体]
看到这样,真是内心很郁闷,什么鬼?为毛会这样!!!为毛加了个 JTextField 后就没有立即显示了?那试试只有一个 JTextField 呢?如下
只有一个 JTextField 的测试
public class Test {
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
panel.setLayout(null);
frame.setContentPane(panel);
frame.setBounds(100, 100, 200, 200);
frame.setVisible(true);
JTextField field = new JTextField();
field.setSize(100, 10);
panel.add(field);
}
}
[运行结果]
[拉伸窗体]
还是一样的没有立即显示!真是日了,什么鬼?JFrame 添加的组件不能立即显示,还得拉伸窗体才会显示是为毛?忍着恶心烦躁,本着程序猿的干掉 bug 的态度,查资料。最后发现,窗体 JFrame 的语句,必须得放在最后面执行,只有这样才能不出现这种神经病的问题。
修改版 Main.java
public class Main{
private static final int FRAME_WIDTH = 600;
private static final int FRAME_HEIGHT = 600;
private String title = "主界面"; // 窗体标题
private JPanel contentPanel;
/**
- 初始化控件
*/
public void initViews () {
contentPanel = new JPanel(); // 创建一个中间容器对象
contentPanel.setLayout(null);
JLabel jl_in = new JLabel("请选择pcap文件:");
jl_in.setBounds(10, 10, 120, 35);
JLabel jl_out = new JLabel("请选择输出目录:");
jl_out.setBounds(10, 70, 120, 35);
JLabel jl_status = new JLabel("程序运行状态:");
jl_status.setBounds(10, 130, 120, 35);
JTextField jtf = new JTextField();
jtf.setBounds(10, 10, 100, 50);
contentPanel.add(jl_in);
contentPanel.add(jl_out);
contentPanel.add(jl_status);
contentPanel.add(jtf);
// 得到屏幕尺寸
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int screenWidth = screenSize.width;
int screenHeight = screenSize.height;
int width = (screenWidth - FRAME_WIDTH) / 2; // x 轴位移
int height = (screenHeight - FRAME_HEIGHT) / 2; // y 轴位移
JFrame jf_main = new JFrame(this.title);
jf_main.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jf_main.setBounds(width, height, FRAME_WIDTH, FRAME_HEIGHT);
jf_main.setResizable(false); // 去掉窗体最大化
jf_main.pack();
jf_main.setVisible(true);
jf_main.setContentPane(contentPanel); // 设置 JFrame 的内容面板
}
public Main(String title) {
this.title = title;
}
public static void main(String[] args) {
new Main("PcapAnalyzer").initViews();;
}
}
[运行结果]
终于解决了,就这鸡毛的问题,恶心了我2个多小时,太心酸了!给自己鼓掌!!!