newborn
newborn

Reputation: 159

How to access a JButton from another class

I have two classes 'UserInterface' and a 'GameEngine' I have declared a JButton component in the UserInterface and I am trying to use one of the variables i.e use the variable 'button1' from 'UserInterface' in the 'horizontalWin' method from the class 'GameEngine'.

I got this error instead "cannot find symbol - variable button1"

Userinterface:

public class UserInterface implements ActionListener
{
 private GameEngine game;
 private JFrame frame;

 JButton button1 = new JButton("");
 JButton button2 = new JButton("");
 JButton button3 = new JButton("");
 JButton button4 = new JButton("");
 JButton button5 = new JButton("");
 JButton button6 = new JButton("");
 JButton button7 = new JButton("");
 JButton button8 = new JButton("");
 JButton button9 = new JButton("");

 /**
 * Create a user interface.
 * @param engine The game's engine.
 */
 public UserInterface(GameEngine engine)
 {
    game = engine;
    makeFrame();
 }

 //some methods
}

GameEngine:

public class GameEngine {
 private String buttonName;
 boolean winner = false;
 byte count;

public GameEngine()
{
    count = 0;
}

public void horizontalWin()
{
    if(button1.getText()==button2.getText() && button2.getText()==button3.getText() && button1.getText()!="" )
    {
        winner=true;
        playAgain(buttonName);

    }
    // Horizontal win row 2
    else if(button4.getText()==button5.getText() && button5.getText()==button6.getText() && button4.getText()!="" )
    {
        winner=true;
        playAgain(buttonName);

    }
    // horizontal win row 3
    else if(button7.getText()==button8.getText() && button8.getText()==button9.getText() && button7.getText()!="")
    {
        winner=true;
        playAgain(buttonName);

    }

}

Upvotes: 0

Views: 2255

Answers (1)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285440

I think that you don't really want to do this, that you don't want your game engine trying to obtain variables from the view. Rather why not have your view notify the engine or "model" (usually through something called a "control", when a button has been pressed. The engine then can keep track of what has been pressed and change its state accordingly. The View can then change in response to changes in the engine's state.

For example:

import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
import javax.swing.event.SwingPropertyChangeSupport;

public class TicTacToe  {

   private static void createAndShowGui() {
      View mainPanel = new View();

      JFrame frame = new JFrame("TicTacToe");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

@SuppressWarnings("serial")
class View extends JPanel {
   private static final int GAP = 2;
   private static final Font BTN_FONT = new Font(Font.SANS_SERIF, Font.BOLD, 42);
   private JButton[][] gameGrid = new JButton[Engine.ROWS][Engine.ROWS];
   private Engine engine = new Engine();

   public View() {
      engine.addPropertyChangeListener(Engine.GAME_OVER, new GameOverListener());

      JPanel gameGridPanel = new JPanel(new GridLayout(Engine.ROWS, Engine.ROWS, GAP, GAP));
      for (int i = 0; i < gameGrid.length; i++) {
         for (int j = 0; j < gameGrid[i].length; j++) {
            gameGrid[i][j] = createGameGridButton(i, j);
            gameGridPanel.add(gameGrid[i][j]);
         }
      }

      JButton resetBtn = new JButton(new ResetAction("Reset", KeyEvent.VK_R));
      JPanel northPanel = new JPanel();
      northPanel.add(resetBtn);

      setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
      setLayout(new BorderLayout(GAP, GAP));
      add(gameGridPanel, BorderLayout.CENTER);
      add(northPanel, BorderLayout.NORTH);
   }

   private JButton createGameGridButton(int i, int j) {
      JButton button = new JButton();
      button.setName(String.format("%d,%d", i, j));
      button.setText(XO.BLANK.getText());
      button.setFont(BTN_FONT);
      button.addActionListener(new GridButtonListener(i, j));
      return button;
   }

   private class GridButtonListener implements ActionListener {
      private int i;
      private int j;

      public GridButtonListener(int i, int j) {
         this.i = i;
         this.j = j;
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         if (engine.isGameOver()) {
            return;
         }
         AbstractButton source = (AbstractButton) e.getSource();
         String text = source.getText();
         if (text.trim().isEmpty()) {
            source.setText(engine.getTurn().getText());
            engine.setXO(i, j);
         }
      }
   }

   private class ResetAction extends AbstractAction {
      public ResetAction(String text, int mnemonic) {
         super(text);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      public void actionPerformed(ActionEvent e) {
         engine.reset();
         for (JButton[] row : gameGrid) {
            for (JButton button : row) {
               button.setText(XO.BLANK.getText());
            }
         }
      };
   }

   private class GameOverListener implements PropertyChangeListener {
      @Override
      public void propertyChange(PropertyChangeEvent evt) {
         if (evt.getNewValue() == Boolean.TRUE) {
            JOptionPane.showMessageDialog(View.this, engine.getTurn()
                  .getText() + " is a winner!", "We Have a Winner!",
                  JOptionPane.INFORMATION_MESSAGE);
         }
      }
   }
}

class Engine {
   public static final int ROWS = 3;
   public static final String GAME_OVER = "game over";
   private XO[][] grid = new XO[ROWS][ROWS];
   private XO turn = XO.X;
   private boolean gameOver = false;
   private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(
         this);

   public Engine() {
      reset();
   }

   public XO getTurn() {
      return turn;
   }

   public boolean isGameOver() {
      return gameOver;
   }

   public void setXO(int row, int col) {
      grid[row][col] = turn;
      checkForWin(row, col);
      turn = (turn == XO.X) ? XO.O : XO.X;
   }

   public void reset() {
      for (int r = 0; r < grid.length; r++) {
         for (int c = 0; c < grid[r].length; c++) {
            grid[r][c] = XO.BLANK;
         }
      }
      turn = XO.X;
      gameOver = false;
   }

   public void checkForWin(int i, int j) {
      boolean win = true;
      for (int col = 0; col < grid.length; col++) {
         if (grid[col][j] != turn) {
            win = false;
         }
      }
      if (!win) {
         win = true;
         for (int row = 0; row < grid[i].length; row++) {
            if (grid[i][row] != turn) {
               win = false;
            }
         }
      }
      if (!win && i == j) {
         win = true;
         for (int k = 0; k < grid.length; k++) {
            if (grid[k][k] != turn) {
               win = false;
            }
         }
      }
      if (!win && i + j == 2) {
         win = true;
         for (int k = 0; k < grid.length; k++) {
            if (grid[k][2 - k] != turn) {
               win = false;
            }
         }
      }

      if (win) {
         setGameOver(true);
      }

   }

   private void setGameOver(boolean gameOver) {
      boolean oldValue = this.gameOver;
      boolean newValue = gameOver;
      this.gameOver = gameOver;
      pcSupport.firePropertyChange(GAME_OVER, oldValue, newValue);
   }

   public void addPropertyChangeListener(PropertyChangeListener listener) {
      pcSupport.addPropertyChangeListener(listener);
   }

   public void removePropertyChangeListener(PropertyChangeListener listener) {
      pcSupport.removePropertyChangeListener(listener);
   }

   public void addPropertyChangeListener(String name,
         PropertyChangeListener listener) {
      pcSupport.addPropertyChangeListener(name, listener);
   }

   public void removePropertyChangeListener(String name,
         PropertyChangeListener listener) {
      pcSupport.removePropertyChangeListener(name, listener);
   }

}

enum XO {
   X("X"), O("O"), BLANK("   ");
   private String text;

   private XO(String text) {
      this.text = text;
   }

   public String getText() {
      return text;
   }
}

My view's ActionListener (here an AbstractAction) notifies the Engine that a certain button has been pushed. The Engine keeps track of which button has been pushed, and when a winner has been determined, sets a gameOver field thereby notifying all listeners that the game is over.

Upvotes: 2

Related Questions