gpt4 book ai didi

java - 从 Controller JavaFX 打开新场景

转载 作者:行者123 更新时间:2023-12-02 02:50:30 24 4
gpt4 key购买 nike

我正在设计一个西洋跳棋游戏,游戏完成后,会打开一个新窗口,您可以在其中开始新游戏或退出。我对 JavaFX 不太了解,并且我已经尝试了一段时间让我的代码正常工作,但我没有成功......

我有一个困难,我的板没有显示为 fxml 文件,但它是用 javacode 创建的并放在 borderPane 的中心。 borderPane 的顶部是 fxml 文件。然后,游戏结束后,另一个窗口也是另一个 fxml 文件:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.text.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>

<Pane fx:id="paneMenu" nodeOrientation="LEFT_TO_RIGHT" prefHeight="160.0" prefWidth="240.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.GameMenuController">

<children>
<Button fx:id="buttonRestart" layoutX="15.0" layoutY="122.0" mnemonicParsing="false" onAction="#restart" prefHeight="27.0" prefWidth="90.0" text="New Game" />
<Button fx:id="buttonQuit" layoutX="139.0" layoutY="122.0" mnemonicParsing="false" onAction="#quit" prefHeight="27.0" prefWidth="90.0" text="Quit" />
<Label fx:id="labelWinner" alignment="CENTER" contentDisplay="CENTER" layoutX="23.0" layoutY="80.0" prefHeight="17.0" prefWidth="190.0" text="Label" textAlignment="CENTER" />
<Text layoutX="50.0" layoutY="47.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Game over!" textAlignment="CENTER">
<font>
<Font size="26.0" />
</font>
</Text>
</children>
<padding>
<Insets bottom="10.0" right="10.0" />
</padding>
</Pane>

此 fxml 文件的 Controller 类如下所示:

public class GameMenuController implements Initializable {

public GameMenuController(Checkers model) {
this.content = model;
}

Checkers content;

@FXML
private Label labelWinner;

@FXML
private Button buttonRestart;

@FXML
private Button buttonQuit;

@FXML
private Pane paneMenu;

BooleanProperty doRestart = new SimpleBooleanProperty(false);

@FXML
void restart(ActionEvent event) {
content.cleanup();
doRestart.set(true);
}

@FXML
void quit(ActionEvent event) {
System.exit(0);
}

@Override
public void initialize(URL location, ResourceBundle resources) {
labelWinner.setText("Winner here.");
labelWinner.textProperty().bind(Bindings.createStringBinding(() -> {
String s = " ";
if (...);
return s;
}, content.whiteTurnProp));
}

}

最后,在我的主类中,我想向值 doRestart 添加一个 ChangeListener,以便重新创建一个新场景。

我的主类看起来像这样:

public class Main extends Application{

Checkers content = new Checkers();
BorderPane border = new BorderPane();
Pane paneBoard = new Pane();
FXMLLoader loader1 = new FXMLLoader();
FXMLLoader loader2 = new FXMLLoader();

@Override
public void start(Stage primaryStage) throws Exception {

loader1.setLocation(getClass().getResource("sample.fxml"));
loader1.setControllerFactory(new Callback<Class<?>, Object>() {
@Override
public Object call(Class<?> aClass) {
return new SampleController(content);
}
});

loader2.setLocation(getClass().getResource("GameMenu.fxml"));
loader2.setControllerFactory(new Callback<Class<?>, Object>() {
@Override
public Object call(Class<?> aClass) {
return new GameMenuController(content);
}
});
GameMenuController gameMenuControl = loader2.getController();

Scene scene = new Scene(startGame());
primaryStage.setTitle("Checkers");
primaryStage.setScene(scene);
primaryStage.show();

content.gameOver.addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
try {
scene.setRoot(loader2.load());
primaryStage.setHeight(180);
primaryStage.setWidth(240);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

});

gameMenuControl.doRestart.addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if(newValue) {
scene.setRoot(startGame());
primaryStage.setHeight(scene.getHeight());
primaryStage.setWidth(scene.getWidth());
gameMenuControl.doRestart.set(false);
}
}
});
}

public static void main(String[] args) {
launch(args);
}
protected Pane createContent() {

paneBoard.setPrefSize(Checkers.WIDTH * Checkers.TILE_SIZE, Checkers.HEIGHT * Checkers.TILE_SIZE);
paneBoard.getChildren().addAll(content.tileGroup, content.pieceGroup);

for (int y = 0; y < Checkers.HEIGHT; y++) {
for (int x = 0; x < Checkers.WIDTH; x++) {
Tile tile = new Tile((x + y) % 2 == 0, x, y);
Checkers.board[y][x] = tile;

content.tileGroup.getChildren().add(tile);

Piece piece = null;

if (y <= 3 && (x + y) % 2 != 0) {
piece = content.makePiece(PieceType.BLACK, x, y);
}

if (y >= 6 && (x + y) % 2 != 0) {
piece = content.makePiece(PieceType.WHITE, x, y);
}

if (piece != null) {
tile.setPiece(piece);
content.pieceGroup.getChildren().add(piece);
}
}
}

return paneBoard;
}

protected BorderPane startGame() {
try {
border.setTop(loader1.load());
} catch (IOException e) {
e.printStackTrace();
}
border.setCenter(createContent());

return border;
}

}

我很确定我的代码一团糟,我一直在尝试尽可能多地使用这里给出的提示,但由于我对此仍然非常陌生,我真的不知道如何去做这一切吧。

我想做的,不是使用这个更改监听器(这也不起作用,我收到 NullPointerException),而是直接从我的 Controller 更改 View 。我该怎么办?

1)我可以不通过工厂创建 Controller ,而是让他们以其他方式访问我的模型检查器吗? (所有游戏逻辑都存储在那里等)

2)我基本上如何重新创建我的第一个窗口? (由 startGame() 创建)

非常感谢!!最好的,丽莎

最佳答案

您在调用loader2.load()之前调用GameMenuController gameMenuControl = loader2.getController()。 Controller 是作为加载过程的一部分创建的,因此 gameMenuControl 将为 null。

您可以简单地将对 loader2.getController()gameMenuControl.doRestart.addListener(...) 的调用移至调用 loader2.load 之后立即进行().

或者,您可以自己创建 Controller ,而不是委托(delegate)给 Controller 工厂。 从 FXML 文件中删除 fx:controller 属性,然后执行以下操作:

@Override
public void start(Stage primaryStage) throws Exception {

// You can make similar changes to loader1 if you want...

loader2.setLocation(getClass().getResource("GameMenu.fxml"));

GameMenuController gameMenuControl = new GameMenuController(content) ;

gameMenuControl.doRestart.addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if(newValue) {
scene.setRoot(startGame());
primaryStage.setHeight(scene.getHeight());
primaryStage.setWidth(scene.getWidth());
gameMenuControl.doRestart.set(false);
}
}
});

loader2.setController(gameMenuControl);

content.gameOver.addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
try {
scene.setRoot(loader2.load());
primaryStage.setHeight(180);
primaryStage.setWidth(240);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

});

Scene scene = new Scene(startGame());
primaryStage.setTitle("Checkers");
primaryStage.setScene(scene);
primaryStage.show();


}

关于java - 从 Controller JavaFX 打开新场景,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43921629/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com