简体   繁体   English

如何从另一个类访问JButton

[英]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 ie use the variable 'button1' from 'UserInterface' in the 'horizontalWin' method from the class 'GameEngine'. 我有两个类'UserInterface'和'GameEngine',我已经在UserInterface中声明了一个JButton组件,我试图使用其中一个变量,即使用来自'UserInterface'中变量'button1'的'horizo​​ntalWin'方法中的类“ GameEngine”。

I got this error instead "cannot find symbol - variable button1" 我收到此错误,而是“找不到符号-变量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: 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);

    }

}

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. 我视图的ActionListener(在这里是AbstractAction)通知引擎某个按钮已被按下。 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. 引擎跟踪按下了哪个按钮,并在确定获胜者时设置gameOver字段,从而通知所有听众游戏已结束。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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