场景元素在javafx中显示两次?

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

我正在用javafx为我做的这个小棋盘游戏应用构建一个UI。它只有Othello和Connect Four,你还可以添加玩家来记分。分数只是记录在一个.txt文件中,并在程序启动时加载。

主菜单是一个带有记分牌的场景,由.txt文件创建,还有按钮。我可以添加球员,他们被写入文件并加载就好了,问题发生在我试图重新加载.txt文件中的球员并刷新记分牌时。我尝试刷新场景,但记分牌被打印了两次。

下面是代码。

import java.io.*;
import java.util.*;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import javafx.geometry.*;

public class Main extends Application {

    static Stage window;

    public void refreshMainMenu() {

        Button c4button = new Button("Connect Four");
        Button othelloButton = new Button("Othello");
        Button addPlayerButton = new Button("Add New Player");
        Button quitButton = new Button("Quit");

        GridPane scoreboard = new GridPane();
        if(!Player.loadPlayers()) {
            Label label = new Label("No Players Yet");
            scoreboard.add(label, 0, 0);
        }
        else {
            Label label = new Label("Scoreboard:\n");
            Label temp1 = new Label("Name\t");
            Label temp2 = new Label("Othello Wins\t");
            Label temp3 = new Label("Connect Four Wins\t");
            Label temp4 = new Label("Total Wins\t");
            scoreboard.add(label, 0, 0);
            scoreboard.add(temp1, 0, 1);
            scoreboard.add(temp2, 1, 1);
            scoreboard.add(temp3, 2, 1);
            scoreboard.add(temp4, 3, 1);

            for(int i = 0; i < Player.getPlayerList().size(); i++) {
                Label temp5 = new Label(Player.getPlayerList().get(i).getName());
                Label temp6 = new Label(Integer.toString(Player.getPlayerList().get(i).getOthelloWins()));
                Label temp7 = new Label(Integer.toString(Player.getPlayerList().get(i).getConnectFourWins()));
                Label temp8 = new Label(Integer.toString(Player.getPlayerList().get(i).getTotalWins()));

                scoreboard.add(temp5, 0, i+2);
                scoreboard.add(temp6, 1, i+2);
                scoreboard.add(temp7, 2, i+2);
                scoreboard.add(temp8, 3, i+2);
            }
        }
        scoreboard.setAlignment(Pos.CENTER);

        HBox buttons = new HBox(20);
        buttons.getChildren().addAll(c4button, othelloButton, addPlayerButton, quitButton);
        buttons.setAlignment(Pos.CENTER);

        VBox layout = new VBox(10);
        layout.getChildren().addAll(scoreboard, buttons);
        layout.setAlignment(Pos.CENTER);

        Scene mainMenu = new Scene(layout, 600, 300);

        window.setScene(mainMenu);
        window.show();

        c4button.setOnAction(e -> {
            try {
                ConnectFour.playConnectFour();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        });
        othelloButton.setOnAction(e -> {
            try {
                Othello.playOthello();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        });
        addPlayerButton.setOnAction(e -> {
            try {
                String newPlayer = TextBox.display("Add Player", "Enter Player Name:");
                Player.addNewPlayer(newPlayer);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            refreshMainMenu();
        });
        quitButton.setOnAction(e -> {
            boolean response = ConfirmBox.display("Exit Board Master","Are you sure?");
            if(response)
                window.close();
        });
        window.setOnCloseRequest(e -> {
            e.consume();
            boolean response = ConfirmBox.display("Exit Board Master","Are you sure?");
            if(response)
                window.close();
        });
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        window = primaryStage;
        window.setTitle("Board Master");
        refreshMainMenu();
    }

    public static void main(String[] args) throws IOException {
        launch(args);
    }
}

还有确认和文本框弹出。

import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.scene.layout.*;
import javafx.scene.control.*;

public class ConfirmBox {

    private static boolean response;

    static boolean display(String title, String message) {
        Stage window = new Stage();
        window.setTitle(title);
        window.initModality(Modality.APPLICATION_MODAL);

        Button yesButton = new Button("Yes");
        Button noButton = new Button("No");
        yesButton.setOnAction(e -> {
            response = true;
            window.close();
        });
        noButton.setOnAction(e -> {
            response = false;
            window.close();
        });

        Label label = new Label(message);
        StackPane toplayout = new StackPane(label);

        HBox centerlayout = new HBox(10);
        centerlayout.getChildren().addAll(yesButton, noButton);
        centerlayout.setAlignment(Pos.CENTER);

        BorderPane layout = new BorderPane();
        layout.setPadding(new Insets(5,5,5,5));
        layout.setTop(toplayout);
        layout.setCenter(centerlayout);

        Scene alertBox = new Scene(layout, 250, 60);
        window.setScene(alertBox);
        window.showAndWait();

        return response;
    }
}

还有..:

import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.scene.layout.*;
import javafx.scene.control.*;

public class TextBox {

    private static String response;

    static String display(String title, String message) {
        Stage window = new Stage();
        window.setTitle(title);
        window.initModality(Modality.APPLICATION_MODAL);

        Label label = new Label(message);
        TextField input = new TextField();
        Button confirmButton = new Button("Confirm");
        confirmButton.setOnAction(e -> {
             response = input.getText();
             window.close();
        });

        VBox layout = new VBox(5);
        layout.getChildren().addAll(label, input, confirmButton);

        Scene textBox = new Scene(layout, 250, 80);
        window.setScene(textBox);
        window.showAndWait();

        return response;
    }
}

还有球员类

import java.io.*;
import java.util.*;

public class Player {

    private String name;
    private int totalWins = 0;
    private int othelloWins = 0;
    private int connectFourWins = 0;

    private static ArrayList<Player> playerList = new ArrayList<>(1);

    private Player(String input) {
        name = input;
    }
    private Player(String input, int othello, int connectFour, int total) {
        name = input;
        othelloWins = othello;
        connectFourWins = connectFour;
        totalWins = total;
    }

    void addOthelloWin() {
        othelloWins++;
        totalWins++;
    }
    void addConnectFourWin() {
        connectFourWins++;
        totalWins++;
    }
    void changeName(String input) {
        name = input;
    }

    static ArrayList<Player> getPlayerList() {
        return playerList;
    }
    static Player getPlayer(String input) {
        for(int i = 0; i < playerList.size(); i++) {
            if(playerList.get(i).name.equals(input)) {
                return playerList.get(i);
            }
        }
        return null;
    }
    String getName() {
        return name;
    }
    int getOthelloWins() {
        return othelloWins;
    }
    int getConnectFourWins() {
        return connectFourWins;
    }
    int getTotalWins() {
        return totalWins;
    }

    static void printWins() {
        System.out.println("Names\t\tOthello\t\tConnect4\t\tTotal" + "\n");
        for(int i = 0; i < playerList.size(); i++)
            System.out.println(playerList.get(i).name + "\t\t\t" + playerList.get(i).othelloWins + "\t\t\t" +
                    playerList.get(i).connectFourWins + "\t\t\t" + playerList.get(i).totalWins);
        System.out.println();
    }

    static void addNewPlayer(String name) throws IOException {
        Player newPlayer = new Player(name);
        playerList.add(newPlayer);

        File file = new File("player_Data.txt");
        FileWriter writer = new FileWriter(file, true);
        writer.write(newPlayer.name + "\t\t" + newPlayer.othelloWins + "\t\t" + newPlayer.connectFourWins + "\t\t" + newPlayer.totalWins + System.lineSeparator());
        writer.close();
    }

    static boolean loadPlayers(){
        Scanner input;

        try {
            File file = new File("player_Data.txt");
            input = new Scanner(file);
        } catch (FileNotFoundException e) {
            return false;
        }

        while (input.hasNextLine()) {
            try {
                String line = input.nextLine();
                String[] lineArray = line.split("\t\t");
                Player newPlayer = new Player(lineArray[0], Integer.parseInt(lineArray[1]), Integer.parseInt(lineArray[2]), Integer.parseInt(lineArray[3]));
                playerList.add(newPlayer);
            } catch (Exception e) {
                System.out.println("Player data incorrectly formatted.");
                break;
            }
        }
        return true;
    }

    static void recordWins() throws IOException {
        File file = new File("player_Data.txt");
        FileWriter writer = new FileWriter(file);

        for(int i = 0; i < playerList.size(); i++) {
            writer.write(playerList.get(i).name + "\t\t" + playerList.get(i).othelloWins + "\t\t" + playerList.get(i).connectFourWins + "\t\t" + playerList.get(i).totalWins + System.lineSeparator());
        }
        writer.close();
    }
}

下面是一个运行示例:在没有数据的情况下打开

添加球员。

添加球员后记分牌显示两次。

关闭并重新启动程序后,记分牌显示球员已被添加并正确加载。

这是我第一次尝试javafx应用程序,所以可能我对它的工作原理感到困惑。我的想法是,我们有一个窗口来显示不同的场景。我让一个场景是一个主菜单,它由 refreshMainMenu()来显示。每当我们添加一个新玩家时,主菜单就会被刷新,但是如果我们点击Othello或Connect Four按钮,那么我们就会切换到Othello的场景或Connect Four的场景。这就是为什么在用户点击添加新玩家并添加玩家后,我调用refreshMainMenu(),它会用新的玩家数据从头开始重新创建主菜单场景。我试过移动我调用refreshMainMenu()的地方,也试过关闭窗口然后调用refreshMainMenu()。关闭窗口后再调用刷新,结果还是同样的记分牌被重复的问题。

这也是我第一次在这里发帖,所以如果我违反了任何规则或者这个问题以前被问过,我很抱歉。我搜索了一下,没有找到真正对我的情况有帮助的帖子。还有运行黑白棋和联通四国游戏的类,但由于我还没有到那一步,所以暂时还是在控制台中运行。如果需要的话,我可以把代码包括进去。

java javafx javafx-8
1个回答
0
投票

呼叫 refreshMainMenu() 方法将玩家列表中的玩家翻倍。if(!Player.loadPlayers()) 加载存储在txt文件中的球员,而不检查球员是否已经存储在txt文件中。Player.playerList 列表。

我决定帮助你,因为你花了很多精力来创建这个问题,而且从代码的质量可以看出你刚刚开始使用JavaFx。给你几个好的建议。你不需要每次想要刷新的时候都改变场景。这是非常不好的做法。学习JavaFx中的可观察集合。玩家不应该存储玩家的列表。首先--学会使用调试器。

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