JavaFX仅使用调试和断点更新图形
我正在通过RMI使用javaFX为棋盘游戏创建GUI。 我有很多问题,因为在找到了更新GUI的方法之后,如果我不在某一行中放置切换断点,我就无法真正更新GUI 如果我不是在调试模式下启动我的客户机,图形似乎不会进行更新,它们只是出现,不再发生任何事情 此外,如果我没有将切换放置在代码的指定行中,而将其放置在另一行(在方法调用序列的更深处),则不会发生任何事情。因此客户端线程不会停止;就好像它不执行它对断点执行的方法调用一样。 我在同一台机器上启动所有客户机,只有一台(使用切换断点)得到更新 现在我将向您展示我的代码 javafx从名为RMIGUIView.java的clas中开始JavaFX仅使用调试和断点更新图形,java,user-interface,debugging,javafx,breakpoints,Java,User Interface,Debugging,Javafx,Breakpoints,我正在通过RMI使用javaFX为棋盘游戏创建GUI。 我有很多问题,因为在找到了更新GUI的方法之后,如果我不在某一行中放置切换断点,我就无法真正更新GUI 如果我不是在调试模式下启动我的客户机,图形似乎不会进行更新,它们只是出现,不再发生任何事情 此外,如果我没有将切换放置在代码的指定行中,而将其放置在另一行(在方法调用序列的更深处),则不会发生任何事情。因此客户端线程不会停止;就好像它不执行它对断点执行的方法调用一样。 我在同一台机器上启动所有客户机,只有一台(使用切换断点)得到更新 现在
@Override
public synchronized void run() {
waiting = true;
pause();
guiDisplayer = new GUIDisplayer();
(new Thread(() -> guiDisplayer.startGUI())).start();
waiting = false;
do {
state.acceptView(this);
} while(!endGame);
}
然后启动GUI(在启动方法中,我按照此处的建议将阶段保存在控制器上
启动gui后,我返回RMIGUIView.java并执行此操作
@Override
public void visit(StartTurnState currentState) {
GUIController guiController = new GUIController();
guiController.updateGUI(currentState);
}
public class GUIController {
@FXML
ArrayList<ImageView> citiesImagesList;
@FXML
Group group;
@FXML
TableView<Player> players;
@FXML
TableColumn<Player, String> playerName;
@FXML
TableColumn<Player, String> victoryPoints;
@FXML
TableColumn<Player, String> coins;
@FXML
TableColumn<Player, String> assistants;
@FXML
TableColumn<Player, String> nobilityPoints;
@FXML
ImageView A;
@FXML
ImageView B;
@FXML
ImageView C;
@FXML
ImageView D;
@FXML
ImageView E;
@FXML
ImageView F;
@FXML
ImageView G;
@FXML
ImageView H;
@FXML
ImageView I;
@FXML
ImageView J;
@FXML
ImageView K;
@FXML
ImageView L;
@FXML
ImageView M;
@FXML
ImageView N;
@FXML
ImageView O;
@FXML
ImageView king;
private static StartTurnState currentState;
private static GUIController self = null;
private static Stage stage;
public GUIController() {
self = this;
}
private void placeRewardToken(Group group, List<ImageView> citiesImagesList) {
Map<String, City> citiesMap = GUIController.currentState.getGameMap().getCitiesMap();
for (ImageView imageView : citiesImagesList) {
City city = citiesMap.get(imageView.getId().toString());
if (city instanceof NormalCity) {
RewardToken rewardToken = ((NormalCity) city).getRewardToken();
Text text = new Text();
text.setText(rewardToken.toString());
text.setX(imageView.getLayoutX() + 5.00);
text.setY(imageView.getLayoutY());
text.toFront();
text.setFont(Font.font("Verdana", 12));
text.setFill(Color.MAGENTA);
group.getChildren().add(text);
}
}
}
private void setPlayerSet() {
Platform.setImplicitExit(false);
Scene scene = stage.getScene();
ObservableList<Player> playersList = FXCollections.observableArrayList();
playersList.addAll(GUIController.currentState.getPlayerSet().getPlayers());
TableView<Player> playerTable = (TableView<Player>) scene.lookup("#players");
TableColumn<Player, String> playersName = ((TableColumn<Player, String>) playerTable.getColumns().get(0));
playersName.setCellValueFactory(new PropertyValueFactory<Player, String>("name"));
TableColumn<Player, String> victoryPoints = ((TableColumn<Player, String>) playerTable.getColumns().get(1));
victoryPoints.setCellValueFactory(new PropertyValueFactory<Player, String>("victoryPoints"));
TableColumn<Player, String> coins = ((TableColumn<Player, String>) playerTable.getColumns().get(2));
coins.setCellValueFactory(new PropertyValueFactory<Player, String>("coins"));
TableColumn<Player, String> assistants = ((TableColumn<Player, String>) playerTable.getColumns().get(3));
assistants.setCellValueFactory(new PropertyValueFactory<Player, String>("assistants"));
TableColumn<Player, String> nobilityPoints = ((TableColumn<Player, String>) playerTable.getColumns().get(4));
nobilityPoints.setCellValueFactory(new PropertyValueFactory<Player, String>("nobilityTrackPoints"));
playerTable.setItems(playersList);
}
private void placeKing(ImageView king, List<ImageView> citiesImagesList) {
for (ImageView imageView : citiesImagesList) {
if (imageView.getId().toString().equals(GUIController.currentState.getKing().getPosition().getName())) {
king.setX(imageView.getLayoutX());
king.setY(imageView.getLayoutY());
}
}
}
@FXML
public void initialize() {
self = this;
}
public void setStage(Stage stage) {
this.stage = stage;
}
public void updateGUI(StartTurnState state) {
GUIController.currentState = state;
updateMap(); //here I should set my toggle breakpoint
}
private void updateMap() {
Scene scene = stage.getScene();
List<ImageView> citiesImagesList = new ArrayList<>();
citiesImagesList.add((ImageView) scene.lookup("#A"));
citiesImagesList.add((ImageView) scene.lookup("#B"));
citiesImagesList.add((ImageView) scene.lookup("#C"));
citiesImagesList.add((ImageView) scene.lookup("#D"));
citiesImagesList.add((ImageView) scene.lookup("#E"));
citiesImagesList.add((ImageView) scene.lookup("#F"));
citiesImagesList.add((ImageView) scene.lookup("#G"));
citiesImagesList.add((ImageView) scene.lookup("#H"));
citiesImagesList.add((ImageView) scene.lookup("#I"));
citiesImagesList.add((ImageView) scene.lookup("#J"));
citiesImagesList.add((ImageView) scene.lookup("#K"));
citiesImagesList.add((ImageView) scene.lookup("#L"));
citiesImagesList.add((ImageView) scene.lookup("#M"));
citiesImagesList.add((ImageView) scene.lookup("#N"));
citiesImagesList.add((ImageView) scene.lookup("#O"));
ImageView king = (ImageView) scene.lookup("#king");
Group group = (Group) scene.lookup("#group");
setPlayerSet(); //if I try setting here my toggle the thread doesent stop as the method updateGui() is never called
placeKing(king, citiesImagesList);
placeRewardToken(group, citiesImagesList);
} }
这里是我的控制器类,如果我想发生什么事情,我必须在这里设置切换断点(请阅读类注释)
我还修改了GUIDisplayer类
public class GUIDisplayer extends Application implements Runnable{
private StartTurnState currentState;
private Stage stage;
static GUIController guiController;
public void start(Stage stage) throws Exception {
GUIController controller = new GUIController();
FXMLLoader fxmlLoader = new FXMLLoader();
Parent root = fxmlLoader.load(getClass().getResource("sceneMap.fxml"));
stage.setTitle("Council of Four");
Scene newScene = new Scene(root);
stage.setScene(newScene);
stage.show();
controller.setStage(stage);
setController(controller);
}
public static void startGUI() {
Application.launch();
}
public void setState(State state) {
currentState = (StartTurnState) state;
}
public static void setController(GUIController controller) {
guiController = controller;
}
@Override
public void run() {
guiController.doUpdateGUI(currentState);
} }
runLater方法调用似乎被忽略了,也许我在本例中是由javadoc描述的
如果在JavaFX运行时关闭后调用此方法,则将忽略该调用:不会执行Runnable,也不会引发异常
如果我删除runLater并添加切换括号点,我仍然可以修改GUI。在尝试从其他线程(javafx应用程序线程除外)更新GUI时,您应该使用
Paltform.runLater(()->doUpdateGUI());
您的gui将正确更新。
检查我已经修改了调用runLater的访问,如下所示。@重写公共无效访问(StartTurnState currentState){GUIController GUIController=new GUIController();Platform.runLater(()->GUIController.doUpdateGUI(currentState));},并且我还在调用updateGUI的控制器中创建了che方法doUpdateGUI(currentState)但是当它应该刷新我的GUI时,什么也没有发生?
Platform.runLater(…)
基本上会尽快在FX应用程序线程上运行。不要担心方法的名称,它只是表示该块中的代码不一定会在稍后运行(…)之后的代码之前完成
call。我认为@guleryuz是正确的:这听起来确实像是线程问题,而且似乎您在某处以某种方式阻止了FX应用程序线程。在调用runLater()之前,我尝试了Platform.setImplicitExit(false)以强制runLater(),现在它进入了updateGUI()中但是对stage的引用为null,我得到了一个nullPointerException。为什么我失去了这个引用?我真的无法理解你的代码。似乎有一些字段是任意变为静态的,从非静态上下文调用静态方法。但是你几乎任意地创建了大量的GUIController
实例,这毫无意义:控制器实例是在调用load()时由fxmloader
为您创建的
。您可能应该重新组织代码,以便它从加载程序中检索该实例并仅使用该实例;否则就无法理解发生了什么。哦,还有,Platform.setImplicitExit(…)
与Platform.runLater(…)没有任何关系
。这只意味着FX平台不会在最后一个窗口关闭时自动退出;您可能出于其他原因需要它,但它不会“强制稍后运行(…)
”(无论这意味着什么)。您的棋盘游戏需要快速更新?它需要在每个玩家回合开始时更新,至少每5分钟更新一次。通常在代码中遵循以下方向:避免在javaFX线程之外更改javaFX场景图形(如果您不确定在哪个线程中使用平台。IsFXApplicationRead()),否则您必须使用平台。runLater()但不要过度使用它会导致应用程序延迟。要在其他线程中运行代码,请检查。我问过它的更新速度有多快,以防您想使用javaFX AnimationTimer进行快速更新
@Override
public void visit(StartTurnState currentState) {
guiDisplayer.setState(currentState);
Platform.runLater(()-> guiDisplayer.run());
}
public class GUIDisplayer extends Application implements Runnable{
private StartTurnState currentState;
private Stage stage;
static GUIController guiController;
public void start(Stage stage) throws Exception {
GUIController controller = new GUIController();
FXMLLoader fxmlLoader = new FXMLLoader();
Parent root = fxmlLoader.load(getClass().getResource("sceneMap.fxml"));
stage.setTitle("Council of Four");
Scene newScene = new Scene(root);
stage.setScene(newScene);
stage.show();
controller.setStage(stage);
setController(controller);
}
public static void startGUI() {
Application.launch();
}
public void setState(State state) {
currentState = (StartTurnState) state;
}
public static void setController(GUIController controller) {
guiController = controller;
}
@Override
public void run() {
guiController.doUpdateGUI(currentState);
} }