在 javafx 中显示两次的场景元素?
Scene elements showing twice in javafx?
我正在用 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;
}
}
而玩家class:
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();
}
}
这是一个示例 运行:
Opening with no data
Adding player.
Scoreboard showing twice after adding a player.
After closing and restarting the program, scoreboard shows that players were added and loaded correctly.
这是我第一次尝试 javafx 应用程序,所以我可能对它的工作原理感到困惑。我的想法是我们有一个 window 来展示不同的场景。我有一个场景是主菜单,由 refreshMainMenu() 显示。每当我们添加新玩家时,主菜单都会刷新,但如果我们单击黑白棋或四连棋按钮,我们就会切换到黑白棋场景或四连棋场景。这就是为什么在用户单击添加新播放器并添加播放器后,我调用 refreshMainMenu() 将使用新播放器数据从头开始重新创建主菜单场景。我试过移动调用 refreshMainMenu() 的位置,还尝试关闭 window 然后调用 refreshMainMenu()。关闭 window 并再次调用 refresh 会导致相同的计分板问题被复制。
这也是我第一次 post 在这里,所以如果我违反了任何规则或者之前有人问过这个问题,我很抱歉。我进行了搜索,但没有找到任何对我的案件真正有帮助的 post。还有 classes that 运行 Othello 和 Connect Four 游戏,但它们现在仍然 运行 在控制台中,因为我还没有到达那里。如有必要,我可以包含代码。
调用refreshMainMenu()
方法使玩家列表中的现有玩家加倍。 if(!Player.loadPlayers())
加载存储在 txt 文件中的播放器而不检查播放器是否已存储在 Player.playerList
列表中。
我决定提供帮助,因为您在创建问题时付出了很多努力,而且根据代码的质量,我可以看出您刚刚开始使用 JavaFx。几个好的建议。不需要每次都想刷新就换场景。这是非常糟糕的做法。了解 JavaFx 中的可观察集合。玩家不应存储玩家列表。首先 - 学习使用调试器。
我正在用 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;
}
}
而玩家class:
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();
}
}
这是一个示例 运行: Opening with no data
Adding player.
Scoreboard showing twice after adding a player.
After closing and restarting the program, scoreboard shows that players were added and loaded correctly.
这是我第一次尝试 javafx 应用程序,所以我可能对它的工作原理感到困惑。我的想法是我们有一个 window 来展示不同的场景。我有一个场景是主菜单,由 refreshMainMenu() 显示。每当我们添加新玩家时,主菜单都会刷新,但如果我们单击黑白棋或四连棋按钮,我们就会切换到黑白棋场景或四连棋场景。这就是为什么在用户单击添加新播放器并添加播放器后,我调用 refreshMainMenu() 将使用新播放器数据从头开始重新创建主菜单场景。我试过移动调用 refreshMainMenu() 的位置,还尝试关闭 window 然后调用 refreshMainMenu()。关闭 window 并再次调用 refresh 会导致相同的计分板问题被复制。
这也是我第一次 post 在这里,所以如果我违反了任何规则或者之前有人问过这个问题,我很抱歉。我进行了搜索,但没有找到任何对我的案件真正有帮助的 post。还有 classes that 运行 Othello 和 Connect Four 游戏,但它们现在仍然 运行 在控制台中,因为我还没有到达那里。如有必要,我可以包含代码。
调用refreshMainMenu()
方法使玩家列表中的现有玩家加倍。 if(!Player.loadPlayers())
加载存储在 txt 文件中的播放器而不检查播放器是否已存储在 Player.playerList
列表中。
我决定提供帮助,因为您在创建问题时付出了很多努力,而且根据代码的质量,我可以看出您刚刚开始使用 JavaFx。几个好的建议。不需要每次都想刷新就换场景。这是非常糟糕的做法。了解 JavaFx 中的可观察集合。玩家不应存储玩家列表。首先 - 学习使用调试器。