我正在尝试创建一个简单的石头、剪刀、布程序,并且我已经掌握了基础知识。我目前面临的问题是,每当我单击任一选项(石头、布或剪刀)时,随机生成的计算机选择的图片上方的“计算机”文本会从右向左移动,并且在上方没有正确对齐。图片,使其成为一个比现在更丑陋的设计,在这个早期阶段。
我尝试研究 RowConstraints,但不知道如何应用它。我尝试使用 ColumnConstraints 使行和列变大,但它似乎不起作用。 (可能是因为我做错了)。
我还有另外两个类和一个接口,如果需要我可以提供。这是我的主要程序:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import org.jetbrains.annotations.NotNull;
public class RockPaperScissors extends Application {
static class Player{
private final String username;
private int score;
public Player(String username) {
this.username = username;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}
static class ComputerPlayer extends Player {
public Choice playTurn() {
return Choice.values()
[ThreadLocalRandom.current().nextInt(
0,
Choice.values().length
)];
}
public ComputerPlayer(String username) {
super(username);
}
}
private Label playerNameLabel;
private Label computerNameLabel;
private Button rockButton;
private Button paperButton;
private Button scissorsButton;
private Label resultLabel;
private Player user;
private ComputerPlayer computer;
// A special class that holds three constant values. Rock, paper and sciccors. I can then call these values by the dot operator.
public enum Choice {
ROCK,
PAPER,
SCISSORS
}
// Create an ImageView object for the player and computer choice
private StackPane playerChoiceImageView = new StackPane();
private StackPane computerChoiceImageView = new StackPane();
/**
* Main method to start the game.
*
* @param args The command line arguments.
*/
public static void main(String[] args) {
launch();
}
@Override
public void start(Stage stage) {
// Create the player and computer objects
user = new Player("User");
computer = new ComputerPlayer("Computer");
// Set the title of the stage
stage.setTitle("Rock, Paper, Scissors");
// Create the labels for the player and computer names and make the text white
playerNameLabel = new Label("Player");
computerNameLabel = new Label("Computer");
// Set the font family to "Arial" and the font weight to bold with a size of 20
playerNameLabel.setFont(Font.font("Arial", FontWeight.BOLD, 20));
computerNameLabel.setFont(Font.font("Arial", FontWeight.BOLD, 20));
//playerNameLabel.setStyle("-fx-text-fill: black;");
//computerNameLabel.setStyle("-fx-text-fill: black;");
// Set the alignment and margins for the player label
GridPane.setHalignment(playerNameLabel, HPos.LEFT);
// Insets is a class that represents the distance between the edges of a node and its content.
GridPane.setMargin(playerNameLabel, new Insets(10, 0, 15, 10));
// Set the alignment and margins for the computer label
GridPane.setHalignment(computerNameLabel, HPos.RIGHT);
GridPane.setMargin(computerNameLabel, new Insets(5, 1, 15, 15));
// Set the horizontal grow priority for the computer label, so it will expand if needed
GridPane.setHgrow(computerNameLabel, Priority.ALWAYS);
// Create the Rectangle objects for the buttons with a specified size
Rectangle rockRectangle = createChoiceNode(Choice.ROCK);
Rectangle paperRectangle = createChoiceNode(Choice.PAPER);
Rectangle scissorsRectangle = createChoiceNode(Choice.SCISSORS);
// Create the buttons with the Rectangle objects as their graphic
rockButton = new Button("", rockRectangle);
paperButton = new Button("", paperRectangle);
scissorsButton = new Button("", scissorsRectangle);
// Create the Label object for the result
resultLabel = new Label();
// Create the GridPane object with the game elements
GridPane grid = new GridPane();
// Add the player and computer choice ImageViews to the GridPane
grid.add(playerChoiceImageView, 1, 2);
grid.add(computerChoiceImageView, 6, 2);
// Create the StackPane object and add the ImageView object to it
StackPane root = new StackPane();
grid.add(playerNameLabel, 1, 1);
grid.add(computerNameLabel, 5, 1);
grid.add(rockButton, 3, 5);
grid.add(paperButton, 4, 5);
grid.add(scissorsButton, 5, 5);
grid.add(resultLabel, 1, 6);
// Add the GridPane object to the StackPane
root.getChildren().add(grid);
// Set the size of the StackPane to the size of the stage
root.setPrefSize(stage.getWidth(), stage.getHeight());
Scene scene = new Scene(root, 500, 400);
stage.setScene(scene);
stage.show();
// Set the onAction handler for all buttons
// The setOnAction() method is used to register an event handler for the onAction event, which is triggered when the button is clicked.
//e -> handleButtonClick(Choice.ROCK"): This lambda expression creates an event handler for the rockButton.
//When the rockButton is clicked, the lambda expression is executed, and the handleButtonClick method is called with the Choice.ROCK argument.
rockButton.setOnAction(e -> handleButtonClick(Choice.ROCK));
paperButton.setOnAction(e -> handleButtonClick(Choice.PAPER));
scissorsButton.setOnAction(e -> handleButtonClick(Choice.SCISSORS));
}
private static @NotNull Rectangle createChoiceNode(Choice choice) {
Rectangle rockRectangle = new Rectangle(60, 60);
rockRectangle.setFill(switch (choice) { case ROCK -> Color.BROWN; case PAPER -> Color.ANTIQUEWHITE; case SCISSORS -> Color.DEEPPINK; });
return rockRectangle;
}
private final List<Choice> choices = new ArrayList<>();
private void handleButtonClick(Choice userChoice) {
// Generate a random choice for the computer using the method from the ComputerPlayer class
Choice computerChoice = computer.playTurn();
// Update the images to show the choices the computer and the user made
playerChoiceImageView.getChildren().add(createChoiceNode(userChoice));
computerChoiceImageView.getChildren().add(createChoiceNode(computerChoice));
// Store the choices in the ArrayList
choices.add(userChoice);
choices.add(computerChoice);
// Determine the winner
// Here I use the dot operator to call the special enum class Choice from before.
if (userChoice == computerChoice) {
// It is a tie
} else if ((userChoice == Choice.ROCK && computerChoice == Choice.SCISSORS)
|| (userChoice == Choice.PAPER && computerChoice == Choice.ROCK)
|| (userChoice == Choice.SCISSORS && computerChoice == Choice.PAPER)) {
// The player wins
user.setScore(user.getScore() + 1);
} else {
// The computer wins
computer.setScore(computer.getScore() + 1);
}
// Update resultLabel with the new scores
resultLabel.setText("Player score: " + user.getScore() + "\n" +
"Computer score: " + computer.getScore());
// Set the font family to "Arial" and the font weight to bold with a size of 20
resultLabel.setFont(Font.font("Arial", FontWeight.BOLD, 20));
//resultLabel.setStyle("-fx-text-fill: black;");
}
}
正如评论中所说,你需要掌握布局节点。在这种情况下,我认为
BorderPane
将是最好的根节点。我创建的这个示例使用 VBox
作为根节点,因为我喜欢使用 VBox
作为根节点。使用其他节点可能有更好的方法来做到这一点。另外,如评论中所述,使用 SceneBuilder
可以帮助您找出设置,以使节点完全按照您喜欢的方式布局。在代码中,我尝试将 GUI 分成几个部分,并边工作边处理每个部分。
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Control;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;
public class App extends Application {
@Override
public void start(Stage stage)
{
//Top
//Left Top
Label lblPlayer = new Label("Player");
Button btnPlayer = new Button("Button");
VBox vbLeftTop = new VBox(lblPlayer, btnPlayer);
//Settings
lblPlayer.setFont(Font.font("System", FontWeight.BOLD, 16));
btnPlayer.setPrefSize(90, 75);
vbLeftTop.setAlignment(Pos.CENTER);
//Center Top
Pane panePlaceHolder = new Pane();
//Settings
HBox.setHgrow(panePlaceHolder, Priority.ALWAYS);
//Right Top
Label lblComputer = new Label("Computer");
Button btnComputer = new Button("Button");
VBox vbRightTop = new VBox(lblComputer, btnComputer);
//Setting
lblComputer.setFont(Font.font("System", FontWeight.BOLD, 16));
btnComputer.setPrefSize(90, 75);
vbRightTop.setAlignment(Pos.CENTER);
//Top root
HBox hbTopRoot = new HBox(vbLeftTop, panePlaceHolder, vbRightTop);
//Settings
VBox.setMargin(hbTopRoot, new Insets(10, 10, 0, 10));
//Center
Pane panePlaceHolderTwo = new Pane();
Button btnOne = new Button("Button");
Button btnTwo = new Button("Button");
Button btnThree = new Button("Button");
Pane panePlaceHolderThree = new Pane();
//Settings
HBox.setHgrow(panePlaceHolderTwo, Priority.ALWAYS);
btnOne.setPrefSize(90, 75);
btnTwo.setPrefSize(90, 75);
btnThree.setPrefSize(90, 75);
HBox.setHgrow(panePlaceHolderThree, Priority.ALWAYS);
//Center root
HBox hbCenterRoot = new HBox(panePlaceHolderTwo, btnOne, btnTwo, btnThree, panePlaceHolderThree);
//Settings
VBox.setMargin(hbCenterRoot, new Insets(20, 10, 0, 10));
//Bottom
//Botton one
Label lblPlayerScore = new Label("Player Score:");
Label lblPlayerScoreCount = new Label("0");
HBox hbOne = new HBox(lblPlayerScore, lblPlayerScoreCount);
//Settings
lblPlayerScore.setFont(Font.font("System", FontWeight.NORMAL, 24));
lblPlayerScoreCount.setFont(Font.font("System", FontWeight.NORMAL, 24));
hbOne.setMaxWidth(Control.USE_PREF_SIZE);
hbOne.setSpacing(5);
//Bottom two
Label lblComputerScore = new Label("Computer Score:");
Label lblComputerScoreCount = new Label("0");
HBox hbTwo = new HBox(lblComputerScore, lblComputerScoreCount);
//Settings
lblComputerScore.setFont(Font.font("System", FontWeight.NORMAL, 24));
lblComputerScoreCount.setFont(Font.font("System", FontWeight.NORMAL, 24));
hbTwo.setMaxWidth(Control.USE_PREF_SIZE);
hbTwo.setSpacing(5);
//Bottom root
VBox vbBottomRoot = new VBox(hbOne, hbTwo);
//Settings
vbBottomRoot.setAlignment(Pos.TOP_CENTER);
VBox.setVgrow(vbBottomRoot, Priority.ALWAYS);
vbBottomRoot.setPadding(new Insets(20, 0, 0, 0));
VBox root = new VBox(hbTopRoot, hbCenterRoot, vbBottomRoot);
Scene scene = new Scene(root, 600, 400);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args)
{
launch(args);
}
}