Java中不创建对象如何从另一个类获取变量(Risk游戏场景)
嘿,这个问题我之前做Java GUI项目的时候也碰到过!核心问题其实是你在NomJoueurs里新建的NombreJoueurs对象,和用户实际操作选择玩家数量的那个实例不是同一个——就像你拿了个新的空表单,当然看不到之前填的数字啦。下面给你几个靠谱的解决办法,按推荐程度排序:
1. 直接通过构造函数传递玩家数量(最推荐)
这是最简单直接的方式,当用户在NombreJoueurs里选好玩家数量后,创建NomJoueurs窗口的时候把这个值直接传进去,完全绕开对象实例依赖的问题。
首先修改NomJoueurs的构造函数,让它接收玩家数量参数:
import javax.swing.*; import java.awt.*; public class NomJoueurs extends JFrame { private int nbJoueurs; // 构造函数接收玩家数量 public NomJoueurs(int nbJoueurs) { this.nbJoueurs = nbJoueurs; initUI(); } private void initUI() { setTitle("输入玩家名称"); setLayout(new GridLayout(nbJoueurs, 2)); // 根据数量设置布局 // 循环创建对应数量的TextField for (int i = 0; i < nbJoueurs; i++) { add(new JLabel("玩家" + (i + 1) + "名称:")); add(new JTextField(20)); } pack(); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); } }
然后在NombreJoueurs的按钮点击事件里,获取到选择的数量后,直接传递给NomJoueurs:
// 假设这是NombreJoueurs里的按钮点击事件处理方法 private void onConfirmButtonClicked() { // 这里替换成你获取用户选择数量的逻辑,比如从下拉框或按钮组获取 int selectedNb = 3; // 示例值 // 创建NomJoueurs并传递数量 new NomJoueurs(selectedNb).setVisible(true); // 关闭当前窗口 this.dispose(); }
2. 使用回调接口解耦窗口(适合复杂流程)
如果你的界面跳转逻辑更复杂(比如NombreJoueurs不需要直接创建NomJoueurs,而是由Main类统一管理),可以用回调接口来传递数据,这样两个窗口类之间不会直接依赖。
首先定义一个回调接口:
public interface PlayerCountCallback { void onPlayerCountSelected(int count); }
然后修改NombreJoueurs的构造函数,让它接收这个回调接口:
public class NombreJoueurs extends JFrame { private PlayerCountCallback callback; public NombreJoueurs(PlayerCountCallback callback) { this.callback = callback; initUI(); } private void initUI() { // 初始化你的按钮、选择组件等 JButton confirmBtn = new JButton("确认"); confirmBtn.addActionListener(e -> { int selectedNb = 4; // 替换成实际获取的数量 callback.onPlayerCountSelected(selectedNb); dispose(); }); add(confirmBtn); // 其他UI初始化逻辑 } }
最后在Main类里实现这个回调,创建NomJoueurs:
public class Main { public static void main(String[] args) { SwingUtilities.invokeLater(() -> { // 启动选择玩家数量的窗口,并传入回调 new NombreJoueurs(count -> { // 当用户选择好数量后,创建输入名称的窗口 new NomJoueurs(count).setVisible(true); }).setVisible(true); }); } }
3. 单例模式(不推荐,除非必要)
如果你非要用getter方法获取值,可以把NombreJoueurs做成单例,确保你在NomJoueurs里拿到的是用户操作的同一个实例。但这种方式会增加类之间的耦合,而且如果窗口生命周期处理不好容易出问题,所以谨慎使用。
修改NombreJoueurs为单例:
public class NombreJoueurs extends JFrame { private static NombreJoueurs instance; private int nb_joueurs; // 私有构造函数,禁止外部新建 private NombreJoueurs() { initUI(); } // 获取单例实例 public static NombreJoueurs getInstance() { if (instance == null) { instance = new NombreJoueurs(); } return instance; } // getter方法 public int getNb_joueurs() { return nb_joueurs; } private void initUI() { // 按钮点击时设置nb_joueurs JButton confirmBtn = new JButton("确认"); confirmBtn.addActionListener(e -> { nb_joueurs = 5; // 替换成实际获取的数量 dispose(); }); add(confirmBtn); } }
然后在NomJoueurs里获取值:
public class NomJoueurs extends JFrame { public NomJoueurs() { // 确保用户已经选择过数量后再调用 int nbJoueurs = NombreJoueurs.getInstance().getNb_joueurs(); // 后续创建TextField的逻辑 } }
最后提醒你
一定要确保在调用getter或者创建NomJoueurs之前,用户已经完成了玩家数量的选择操作——如果NomJoueurs窗口在用户点击确认按钮之前就被创建了,那拿到的肯定是nb_joueurs的初始值(比如0)。
内容的提问来源于stack exchange,提问作者Pablo Balian

