The project:
I am creating a tic-tac-toe game in which the user decides the size of the board.
I've figured out how to change the size of the board; fantastic. I've figured out how to fill the board with button objects; awesome.
What I still need to figure out is how do I attach a function/event to each button. I want a button to change its text to either an "X" or "O" when the user clicks on a button. Looking at tutorials, they only show how to do it when you have a specific name fxid for your button and/or when you have already made the button in SceneBuilder and attaching an event to a specific object.
What I'm using:
SceneBuilder / IntelliJ
Below I've listed controller class, main class, and FXML.
The method that decides the size of the board and generates buttons (In Controller Class):
gameBoard is Gridpane used for tic-tac-toe board.
public void changeGameBoard(ActionEvent event){
if (boardNumber > 3){
sizeLabel.setText("Set at :" + boardNumber);
//Generating Columns and Rows
for(int i = 0; i < (boardNumber - 3); i++){
ColumnConstraints column = new ColumnConstraints();
column.setMinWidth(100);
gameBoard.getColumnConstraints().add(column);
RowConstraints row = new RowConstraints();
row.setMinHeight(100);
gameBoard.getRowConstraints().add(row);
}
//Generating Buttons
for(int j = 0; j < boardNumber; j++){
for(int i = 0; i < boardNumber; i++){
Button boardButton = new Button();
boardButton.setMinWidth(100);
boardButton.setMinHeight(100);
boardButton.setText("Blank");
gameBoard.addRow(j,boardButton);
/*for(int j = 0; j <= boardNumber; j++){
gameBoard.add(boardButton, j,i);
}*/
}
}
}
}
Entire Controller Class:
package com.sosgame;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.RowConstraints;
import javafx.scene.text.Text;
public class SosController {
@FXML
private GridPane gameBoard;
@FXML
private RadioButton sButton, gButton, blueSButton, blueOButton, redSButton, redOButton;
@FXML
private TextField boardSizeInput;
@FXML
private Button startButton;
private Button moveButton;
@FXML
private Label sizeLabel;
private int boardNumber = 10;
private String gameMode = new String(" ");
private String bluePlayerMove = " ";
private String redPlayerMove = " ";
private GridPane newGameBoard = new GridPane();
public void setBoardSize(ActionEvent event){
boardNumber = Integer.parseInt(boardSizeInput.getText());
sizeLabel.setText("Set at : " + boardNumber);
}
public int getBoardNumber(){
return boardNumber;
}
public void setGameType(ActionEvent event) {
if (sButton.isSelected()) {
gameMode = sButton.getText();
}
else if (gButton.isSelected()){
gameMode = gButton.getText();
}
}
public String getGameMode() {
return gameMode;
}
public void textAppear(ActionEvent event){
Text lily = new Text();
}
public void changeGameBoard(ActionEvent event){
if (boardNumber > 3){
sizeLabel.setText("Set at :" + boardNumber);
//Generating Columns and Rows
for(int i = 0; i < (boardNumber - 3); i++){
ColumnConstraints column = new ColumnConstraints();
column.setMinWidth(100);
gameBoard.getColumnConstraints().add(column);
RowConstraints row = new RowConstraints();
row.setMinHeight(100);
gameBoard.getRowConstraints().add(row);
}
//Generating Buttons
for(int j = 0; j < boardNumber; j++){
for(int i = 0; i < boardNumber; i++){
Button boardButton = new Button();
boardButton.setMinWidth(100);
boardButton.setMinHeight(100);
boardButton.setText("Blank");
gameBoard.addRow(j,boardButton);
/*for(int j = 0; j <= boardNumber; j++){
gameBoard.add(boardButton, j,i);
}*/
}
}
}
}
public void ButtonChange (ActionEvent event){
}
public void setBluePlayerMoveType(ActionEvent event){
if (blueSButton.isSelected()){
bluePlayerMove = "S";
} else if (blueOButton.isSelected()) {
bluePlayerMove = "O";
}
}
public void setRedPlayerMoveType(ActionEvent event){
if (redSButton.isSelected()){
redPlayerMove = "S";
} else if (redOButton.isSelected()) {
redPlayerMove = "O";
}
}
}
Entire Main Class:
package com.sosgame;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Stage;
import javafx.scene.layout.GridPane;
import java.io.IOException;
public class SosApplication extends Application {
@Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(SosApplication.class.getResource("sos-gui.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 600, 400);
stage.setTitle("Jacob's SOS Game");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
Entire FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.ToggleGroup?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.text.Font?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" onInputMethodTextChanged="#setBoardSize" prefHeight="600.0" prefWidth="606.0" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.sosgame.SosController">
<children>
<RadioButton fx:id="sButton" layoutX="53.0" layoutY="14.0" mnemonicParsing="false" onAction="#setGameType" prefHeight="32.0" prefWidth="104.0" text="Simple Game">
<toggleGroup>
<ToggleGroup fx:id="gameTypeSelected" />
</toggleGroup>
<font>
<Font size="13.0" />
</font>
</RadioButton>
<RadioButton fx:id="gButton" layoutX="209.0" layoutY="14.0" mnemonicParsing="false" onAction="#setGameType" prefHeight="32.0" prefWidth="110.0" text="General Game" toggleGroup="$gameTypeSelected">
<font>
<Font size="13.0" />
</font>
</RadioButton>
<Label layoutX="389.0" layoutY="18.0" prefHeight="25.0" prefWidth="73.0" text="Board Size">
<font>
<Font size="14.0" />
</font>
</Label>
<Label layoutX="34.0" layoutY="130.0" prefHeight="65.0" prefWidth="110.0" text="Blue Player">
<font>
<Font size="20.0" />
</font>
</Label>
<RadioButton fx:id="blueSButton" layoutX="43.0" layoutY="179.0" mnemonicParsing="false" onAction="#setBluePlayerMoveType" prefHeight="32.0" prefWidth="47.0" selected="true" text="S">
<font>
<Font size="18.0" />
</font>
<toggleGroup>
<ToggleGroup fx:id="bluePlayerMoveType" />
</toggleGroup>
</RadioButton>
<RadioButton fx:id="blueOButton" layoutX="43.0" layoutY="220.0" mnemonicParsing="false" onAction="#setBluePlayerMoveType" prefHeight="32.0" prefWidth="47.0" text="O" toggleGroup="$bluePlayerMoveType">
<font>
<Font size="18.0" />
</font>
</RadioButton>
<Label layoutX="461.0" layoutY="126.0" prefHeight="65.0" prefWidth="110.0" text="Red Player">
<font>
<Font size="20.0" />
</font>
</Label>
<RadioButton fx:id="redSButton" layoutX="469.0" layoutY="175.0" mnemonicParsing="false" onAction="#setRedPlayerMoveType" prefHeight="32.0" prefWidth="47.0" selected="true" text="S">
<font>
<Font size="18.0" />
</font>
<toggleGroup>
<ToggleGroup fx:id="redPlayerMoveType" />
</toggleGroup>
</RadioButton>
<RadioButton fx:id="redOButton" layoutX="469.0" layoutY="216.0" mnemonicParsing="false" onAction="#setRedPlayerMoveType" prefHeight="32.0" prefWidth="47.0" text="O" toggleGroup="$redPlayerMoveType">
<font>
<Font size="18.0" />
</font>
</RadioButton>
<GridPane fx:id="gameBoard" gridLinesVisible="true" layoutX="153.0" layoutY="260.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="195.0" prefWidth="194.0">
<columnConstraints>
<ColumnConstraints hgrow="ALWAYS" minWidth="100.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="100.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="100.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="100.0" prefHeight="30.0" vgrow="ALWAYS" />
<RowConstraints minHeight="100.0" prefHeight="30.0" vgrow="ALWAYS" />
<RowConstraints minHeight="100.0" prefHeight="30.0" vgrow="ALWAYS" />
</rowConstraints>
</GridPane>
<Label alignment="CENTER" layoutX="78.0" layoutY="110.0" prefHeight="32.0" prefWidth="445.0" text="Current Player: Blue">
<font>
<Font size="17.0" />
</font>
</Label>
<Button fx:id="startButton" layoutX="212.0" layoutY="85.0" mnemonicParsing="false" onAction="#changeGameBoard" prefHeight="25.0" prefWidth="182.0" text="Start Game" />
<TextField fx:id="boardSizeInput" layoutX="487.0" layoutY="18.0" onAction="#setBoardSize" onInputMethodTextChanged="#setBoardSize" prefHeight="25.0" prefWidth="29.0" />
<Label fx:id="sizeLabel" layoutX="391.0" layoutY="46.0" prefHeight="17.0" prefWidth="94.0" text="Size Label" />
</children>
</AnchorPane>
You set an action event handler using java code on a button like this:
Button button = new Button();
button.setOnAction(e -> myAction());
where myAction
is whatever action you want to take when the button is actioned.
A basic hello, world app demonstrates this.
To do this in a loop, just place the above code in the loop.
To set an action handler from a button defined in FXML, see:
If the button is defined in FXML, the action handlers are not attached in a loop. If you want to attach action handlers in a loop, you should create the associated buttons in a loop as outlined previously rather than in FXML.
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.