简体   繁体   中英

Running GUI Update methods from separate Class methods

I'm creating a playing card game in Java. I have already programmed the whole game logic, including all the rules etc and I have started to implement the GUI on top of that model.

I have 5 classes but the ones I'll be talking about are just the 'Main' or game class and the 'GUI' class. Firstly, in order to construct the hand I use ArrayLists of Object Type < Card > that I have created. The game works by playing through the method 'Play()' and (at the moment) displaying the Human Players Hand to him via the console and asking him to make an integer selection in the ArrayList to place down. I have the main(String[] args) in the class Main and in order to call the class GUI and set up the game board I use.

     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);
            }
        })

Ideally I would like the game to play through using the Play() method and call methods from the GUI class to both update the board and return the human players selection of card. At the moment the best I can do is, when setting up the board I implement a button via

   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();                      
                        }
        });

which then runs

  public void UpdateHand()
    {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                inPlay = main.inPlay;
                UpdateInPlay(inPlay, InPlayDisplay);
                HumanHand = main.humanplayer;
                HumanHandDisplay.removeAll();

when clicked, which clears the panels and repaints the card JLabels back on.

My question is, how can I make the Play() method call methods in the GUI class? When I try to run the UpdateHand() from the Play() method, just using

gui.UpdateHand();

it returns a NullPointerException at that gui.UpdateHand() line, yet still prints the variables inside the UpdateHand() method to console when I tell it to, such as the ArrayList. As I said, instead of having a button on the gui that updates the board, I would like my Play() method to just call the UpdateMethod as it loops round its turn sequence and then when the player needs to make a card selection, instead of using the console scanner that I use now, run a method which adds a text feild and a button to the board for the user to type in their selection, which is then returned to the Play() method to carry on with the game computation.

Can anyone shed any light on what I'm doing wrong and how to achieve what I've specified here?

EDIT:

More of my code for the 2 classes as requested

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);

then i have the updateHand() method which is called via button and does this

                  for (int i = 0; i < (HumanHand.size()); i++)
                {
                    Card card = HumanHand.get(i);

                    BufferedImage cardImage = null;

                    try {

                        cardImage = ImageIO.read(new File("card/" + card + ".jpg"));
                    } catch (IOException e) {
        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    JLabel picLabel = new JLabel(new ImageIcon( cardImage ));
                    HumanHandDisplay.add(picLabel);

                } 

                HumanHandDisplay.updateUI();

My Main class has

public class Main {

    static AI ai;
    public static GUI gui;

found GUI had to be static otherwise i couldn't call it using

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

even when GUI is static it doesnt let me run gui.GUIReturn() for some reason, says it must be static

I think we might need more code to answer this one. To me, it looks like it could be something simple like the scope of your GUI gui variable. In the example you've shown, the scope of gui is only in the run method of the Runnable object you've created.

Traditionally, the proper way to call something in a GUI is to use a Singleton pattern . Basically, that let's you call

GUI.getInstance().myMethod();

Also, on a slight tangent, if that is the only code in your UpdateHand() method, your extra thread is a waste of time because

SwingUtilities.invokeLater(new Runnable(){ ... });

Simply puts the Runnable in the event queue, which waits for its turn to run. So if that was the only thing in your method, the thread would pretty much go away instantly. Though it might not be the only code in there, since you didn't end the bracket, just thought I'd note it.

Lastly, ANYTHING ( except some things... ) that affects the GUI needs to be done in invokeLater. Otherwise you can end up with errors that will drive you crazy because it appears to not be in your code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM