求助:如何将JFrame与JMenuBar代码移出public static void main方法
解决Swing界面不显示的问题:重构main方法中的JFrame与菜单逻辑
我来帮你搞定这个问题!你遇到的界面不显示问题,核心原因是把main里的窗口初始化代码移到GRandom类后,没有正确完成窗口的创建、配置和显示流程,同时还有一些小细节需要修正。咱们一步步来解决:
问题分析
原来的main方法直接完成了JFrame的创建、菜单配置,最后调用了setVisible(true)让窗口显示。但你改成new JMenuTest()(应该是new GRandom()的笔误吧?)后,GRandom类里没有正确执行这些关键步骤,导致窗口被创建了但没被显示出来,甚至菜单条也没关联到窗口上。
解决方案:重构GRandom类
我们把窗口初始化、菜单创建的逻辑封装到GRandom类的构造方法中,同时遵循Swing的最佳实践,确保UI操作在事件调度线程(EDT)中执行。
完整重构后的GRandom代码
import javax.swing.*; import java.awt.*; import java.util.ResourceBundle; public class GRandom { public JPanel JP1; // 假设你已经定义并初始化了这个面板 public GRandom() { // 1. 初始化资源包 ResourceBundle res = ResourceBundle.getBundle("georglider.grandom.lang.lang"); // 2. 创建并配置主窗口 JFrame frame = new JFrame(res.getString("GRandom")); frame.setContentPane(this.JP1); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(300, 163); frame.setResizable(false); // 3. 创建菜单条并绑定到窗口 JMenuBar menuBar = buildMenuBar(); frame.setJMenuBar(menuBar); // 4. 显示窗口(pack先调整布局,再显示) frame.pack(); frame.setVisible(true); } // 单独封装菜单创建逻辑,让代码更清晰易维护 private JMenuBar buildMenuBar() { JMenuBar menuBar = new JMenuBar(); // 创建顶层菜单 JMenu modeMenu = new JMenu("Режим"); JMenu displayMenu = new JMenu("После генерации"); JMenu generateOptionsMenu = new JMenu("Опции для генерации"); menuBar.add(modeMenu); menuBar.add(displayMenu); menuBar.add(generateOptionsMenu); // 创建空图标(保持你原来的实现) Icon emptyIcon = new Icon() { @Override public void paintIcon(Component c, Graphics g, int x, int y) {} @Override public int getIconWidth() { return 0; } @Override public int getIconHeight() { return 0; } }; // --- 模式菜单选项 --- JRadioButtonMenuItem numbersItem = new JRadioButtonMenuItem("Генерировать числа", emptyIcon, true); numbersItem.setActionCommand("Mnumbers"); JRadioButtonMenuItem stringItem = new JRadioButtonMenuItem("Генерировать заданные строки"); stringItem.setActionCommand("Mstring"); // 添加按钮组,确保单选按钮互斥(你原来的代码缺失这一步) ButtonGroup modeGroup = new ButtonGroup(); modeGroup.add(numbersItem); modeGroup.add(stringItem); modeMenu.add(numbersItem); modeMenu.add(stringItem); // --- 显示菜单选项 --- JRadioButtonMenuItem defaultDisplayItem = new JRadioButtonMenuItem("По умолчанию", emptyIcon, true); defaultDisplayItem.setActionCommand("Ddefault"); JRadioButtonMenuItem openFileItem = new JRadioButtonMenuItem("Открыть файл"); openFileItem.setActionCommand("Dopen"); JRadioButtonMenuItem showHereItem = new JRadioButtonMenuItem("Показать здесь"); showHereItem.setActionCommand("Dshowhere"); ButtonGroup displayGroup = new ButtonGroup(); displayGroup.add(defaultDisplayItem); displayGroup.add(openFileItem); displayGroup.add(showHereItem); displayMenu.add(defaultDisplayItem); displayMenu.add(openFileItem); displayMenu.add(showHereItem); // --- 生成选项菜单 --- JRadioButtonMenuItem noNumbersItem = new JRadioButtonMenuItem("Не включать числа"); noNumbersItem.setActionCommand("GOninclude"); // 修正你原来代码里的ActionCommand赋值错误 generateOptionsMenu.add(noNumbersItem); return menuBar; } public static void main(String[] args) { // 关键:Swing组件必须在事件调度线程中创建,避免UI异常 SwingUtilities.invokeLater(() -> { JFrame.setDefaultLookAndFeelDecorated(true); new GRandom(); // 现在创建GRandom实例就会自动初始化并显示窗口 }); } }
关键修正点说明
- 构造方法中完成窗口初始化:当你在main里
new GRandom()时,构造方法会自动执行窗口创建、菜单绑定和显示操作,解决了原来窗口没被显示的问题。 - 添加ButtonGroup:原来的单选菜单没有互斥功能,添加按钮组后同一组的单选按钮只能选中一个,符合预期逻辑。
- 修正ActionCommand错误:你原来的代码里误把
Dshowhere的ActionCommand改成了GOninclude,现在已经修正为给对应的菜单项赋值。 - 使用SwingUtilities.invokeLater:这是Swing开发的最佳实践,确保所有UI操作在EDT中执行,避免线程安全问题和UI卡顿。
额外注意
如果你的JP1面板还没有初始化,记得在GRandom类中先创建并配置这个面板(比如添加组件、设置布局),否则窗口会显示为空。
内容的提问来源于stack exchange,提问作者Georglider
相关产品推荐
相关产品推荐

