当我在 JavaFX 中单击按钮时文本移动

问题描述 投票:0回答:1

我正在尝试创建一个简单的石头、剪刀、布程序,并且我已经掌握了基础知识。我目前面临的问题是,每当我单击任一选项(石头、布或剪刀)时,随机生成的计算机选择的图片上方的“计算机”文本会从右向左移动,并且在上方没有正确对齐。图片,使其成为一个比现在更丑陋的设计,在这个早期阶段。

我尝试研究 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;");
    }
}
java user-interface javafx
1个回答
0
投票

正如评论中所说,你需要掌握布局节点。在这种情况下,我认为

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

输出

© www.soinside.com 2019 - 2024. All rights reserved.