免责声明:我对 JavaFX 和模型- View - Controller 设计原则非常不熟悉。
这是我的基本情况:
我有一个类似于 this 中概述的 ScreenManager教程。使用屏幕管理器,我使用屏幕按钮上的基本操作处理在多个 FXML 屏幕之间切换。
问题是其中一个是带有 map 的游戏画面。我将在这个游戏屏幕上绘制基于图 block 的 map ,因此我在我的 FXML 文件中使用了 TilePane(如果有更好的方法将图 block 绘制到屏幕区域,请告诉我)。
这是我创建要绘制到游戏屏幕的 TilePane 的代码:
public TilePane createRandomMap(boolean centeredRiver)
{
Image atlas = new Image("resources/textures/tile_atlas.jpg");
Random rand = new Random();
int riverPos = 4,
tileHeight = (int)atlas.getHeight()/2,
tileWidth = (int)atlas.getWidth()/3;
if(!centeredRiver)
riverPos = rand.nextInt(10);
for(int i = 0; i < 5; i++)
{
for(int j = 0; j < riverPos; j++)
{
int type = rand.nextInt(4);
Tile tile = new Tile(tileTypes[type], i, j);
tile.setImage(atlas);
tile.setViewport(new Rectangle2D((type%3)*tileWidth, //minX
tileHeight-(type/3)*tileHeight, //minY
tileWidth, tileHeight)); // width, height
tile.setFitHeight(tilePane.getHeight()/5); //fit to the size of the pane
tile.setFitWidth(tilePane.getWidth()/9); //fit to the size of the pane
tile.setPreserveRatio(true);
tilesToAdd.add(tile);
}
if(i == 2)
{
Tile tile = new Tile(tileTypes[5], i, riverPos);
tile.setImage(atlas);
tile.setViewport(new Rectangle2D(2*tileWidth, 0,
tileWidth, tileHeight));
tile.setFitHeight(tilePane.getHeight()/5);
tile.setFitWidth(tilePane.getWidth()/9);
tile.setPreserveRatio(true);
tilesToAdd.add(tile);
}
else
{
Tile tile = new Tile(tileTypes[4], i, riverPos);
tile.setImage(atlas);
tile.setViewport(new Rectangle2D(tileWidth, 0,
tileWidth, tileHeight));
tile.setFitHeight(tilePane.getHeight()/5);
tile.setFitWidth(tilePane.getWidth()/9);
tile.setPreserveRatio(true);
tilesToAdd.add(tile);
}
for(int j = riverPos + 1; j<9; j++)
{
int type = rand.nextInt(4);
Tile tile = new Tile(tileTypes[type], i, j);
tile.setImage(atlas);
tile.setViewport(new Rectangle2D((type%3)*tileWidth, //minX
tileHeight-(type/3)*tileHeight, //minY
tileWidth, tileHeight)); // width, height
tile.setFitHeight(tilePane.getHeight()/5); //fit to the size of the pane
tile.setFitWidth(tilePane.getWidth()/9); //fit to the size of the pane
tile.setPreserveRatio(true);
tilesToAdd.add(tile);
}
}
tilePane.getChildren().addAll(tilesToAdd);
return tilePane;
}
我已经能够在我的 Controller 类中访问这个 TilePane:
public class GameScreenController implements Initializable, ControlledScreen {
ScreenManager screenManager;
@FXML
TilePane mapPane
/**
* Initializes the controller class.
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
TileEngine engine = new TileEngine();
mapPane = engine.createRandomMap(true);
}
在上述实例中,我将 FXML 屏幕中定义的 TilePane 设置为我在模型中创建的 TilePane,但出现以下错误:
Can not set javafx.scene.layout.TilePane field
screens.gameScreen.GameScreenController.mapPane to
javafx.scene.layout.AnchorPane
这是我的 FXML 文件中处理 TilePane 的部分:
<TilePane id="MapPane" fx:id="mapPane" layoutX="0.0" layoutY="0.0" prefColumns="9" prefHeight="560.0" prefTileHeight="112.0" prefTileWidth="112.0" prefWidth="1108.0" visible="true" />
总的来说,我真的很难完全了解 JavaFX 和游戏设计,但非常想学习。我很乐意就此结构的任何部分进行澄清和批评,以使其变得更好,即使是与我要问的问题无关的事情。
提前致谢!
最佳答案
MVC
严格来说,JavaFX 不支持 MVC(发明者自己宣称它已经死了),但支持某种 MVVM(模型- View - View 模型)
模型和 Controller 之间的通信
我通常使用依赖注入(inject)来做到这一点。如果你想要一个简单的框架,我可以建议你 afterburner.fx或谷歌指南。两个非常轻量级的框架都可以做你想做的事。基本上,他们可以为您处理类的实例化,并确保如果需要,您的模型只有一个实例处于 Activity 状态。
一些示例代码:
public class Presenter {
// Injects
@Inject private StateModel stateModel;
}
不需要声明构造函数或任何东西。如果你愿意,你需要做更多的工作来测试它,但总的来说我不想再错过这个功能,因为通常你只想要一个 StateModel
,你的所有信息都来自意见只是听取他们的意见或改变他们。
让我们再举一个例子来扩展到发布的代码
@Singleton
public class StateModel {
// Properties
private final StringProperty name = new SimpleStringProperty();
// Property Getter
public StringProperty nameProperty() { return this.name; }
}
如果我们现在在 Presenter/Controller 中声明了一个标签,我们可以像这样监听模型中的变化
public class Presenter implements Initializable {
// Nodes
@FXML private Label nodeLabelName;
// Injects
@Inject private StateModel stateModel;
@Override
public void initialize(URL location, ResourceBundle resource) {
this.nodeLabelName.textProperty().bind(this.stateModel.nameProperty());
}
}
我可以给你的另一个建议是线程
。您通常希望您的业务逻辑在另一个线程中执行,否则您的应用程序线程在处理时会开始滞后
关于java - 如何在 Java FX FXML 应用程序中的模型和 View 之间进行通信?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19484914/