Java 从单独的类方法运行GUI更新方法

Java 从单独的类方法运行GUI更新方法,java,swing,user-interface,Java,Swing,User Interface,我正在用Java创建一个扑克牌游戏。我已经编写了整个游戏逻辑,包括所有的规则等,我已经开始在该模型上实现GUI 我有5个类,但我要说的只是“Main”或“game”类和“GUI”类。首先,为了构造手,我使用我创建的对象类型的ArrayList。游戏的工作原理是通过“Play()”方法进行游戏,(此时)通过控制台向他显示人类玩家的手,并要求他在ArrayList中进行整数选择以放置下来。我在类main中有main(String[]args),以便调用类GUI并设置我使用的游戏板 publ

我正在用Java创建一个扑克牌游戏。我已经编写了整个游戏逻辑,包括所有的规则等,我已经开始在该模型上实现GUI

我有5个类,但我要说的只是“Main”或“game”类和“GUI”类。首先,为了构造手,我使用我创建的对象类型的ArrayList。游戏的工作原理是通过“Play()”方法进行游戏,(此时)通过控制台向他显示人类玩家的手,并要求他在ArrayList中进行整数选择以放置下来。我在类main中有main(String[]args),以便调用类GUI并设置我使用的游戏板

     public static void main(String[] args)
     {
        Deck deck = new Deck();     
        ai = new AI;

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                GUI gui = new GUI();
                gui.setVisible(true);
            }
        })
理想情况下,我希望通过使用play()方法和GUI类中的调用方法来玩游戏,以更新棋盘并返回人类玩家选择的牌。目前,我能做的最好的事情是,在设置板时,我通过

   Button go = new Button("Update Hand");
   ButtonDisplay.add(go);

   go.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e) {
                Thread queryThread = new Thread() {
            public void run() {
                 UpdateHand();
            }
            };
                queryThread.start();                      
                        }
        });
然后运行

  public void UpdateHand()
    {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                inPlay = main.inPlay;
                UpdateInPlay(inPlay, InPlayDisplay);
                HumanHand = main.humanplayer;
                HumanHandDisplay.removeAll();
单击后,将清除面板并重新绘制卡标签

我的问题是,如何在GUI类中创建Play()方法调用方法?当我尝试从Play()方法运行UpdateHand()时,只需使用

gui.UpdateHand()

它在gui.UpdateHand()行返回一个NullPointerException,但当我告诉它时,仍然会将UpdateHand()方法中的变量打印到控制台,例如ArrayList。正如我所说,我希望我的Play()方法在循环轮换顺序时调用UpdateMethod,然后在玩家需要选择卡片时调用UpdateMethod,而不是使用我现在使用的控制台扫描仪,而不是gui上的按钮来更新棋盘,运行一个方法,在棋盘上添加一个文本字段和一个按钮,供用户输入他们的选择,然后返回Play()方法进行游戏计算

谁能解释一下我做错了什么,以及如何实现我在这里指定的目标

编辑:

根据要求,我为这两个类编写了更多代码

GUI
public class GUI extends JFrame
{
public Main main;
private ArrayList<Card> AIHand;
     public GUI() {

     pane = this.getContentPane();
     pane.setLayout(new GridLayout(6,1,2,2));
     AIBackDisplay = new JPanel();
     //just more of the same for other panels here

     pane.setBackground(Color.GREEN);
     setTitle("Last Man Standing");
     pane.add(AIBackDisplay);
     pane.add(AIHandDisplay);
     pane.add(InPlayDisplay);
     pane.add(HumanHandDisplay);
     pane.add(HumanBackDisplay);
     pane.add(HumanFacedownDisplay);
     pane.add(ButtonDisplay);

       setSize(800, 700);
       setLocationRelativeTo(pane);
       setDefaultCloseOperation(EXIT_ON_CLOSE);


       UpdateFacedown(AIFacedown, AIBackDisplay); //these are methods called for original display
       UpdateFacedown(HumanFacedown, HumanBackDisplay);
发现GUI必须是静态的,否则我无法使用

      Scanner sc = new Scanner (System.in);
                choice = sc.nextInt(); //what i'm using now
                //choice = gui.GUIReturn(); //what i'd like to use

即使GUI是静态的,它也不允许我运行GUI.GUIReturn(),因为某些原因,它说它必须是静态的

我想我们可能需要更多的代码来回答这个问题。在我看来,它可能是一些简单的东西,比如GUI变量的范围。在您展示的示例中,gui的作用域仅在您创建的可运行对象的run方法中

传统上,在GUI中调用某些东西的正确方法是使用。基本上,你打电话吧

GUI.getInstance().myMethod();
另外,如果这是UpdateHand()方法中唯一的代码,那么额外的线程就是浪费时间,因为

SwingUtilities.invokeLater(new Runnable(){ ... });
只需将Runnable放入事件队列,等待轮到它运行。因此,如果这是您的方法中的唯一内容,那么线程几乎会立即消失。虽然它可能不是这里的唯一代码,因为你没有结束括号,我只是想记下它


最后,任何影响GUI的()操作都需要在invokeLater中完成。否则,您可能会遇到一些错误,这些错误会让您发疯,因为代码中似乎没有这些错误。

OK post updated。如果我放置SwingUtilities.invokeLater(new Runnable(){public void run(){choice=gui.GUIReturn();}});它给了我一个错误,告诉我int必须是final,但是我使用int选项的其他地方没有一个可以使用它。我现在已经实现了Singleton,它工作得很好。感谢您的帮助构建一个可能是一个有用的练习。请学习java命名约定并坚持它们。
GUI.getInstance().myMethod();
SwingUtilities.invokeLater(new Runnable(){ ... });