Ich erstelle eine GUI für ein Brettspiel mit javaFX über RMI. Ich habe eine Menge Probleme, denn nachdem ich einen Weg gefunden habe, meine GUI zu aktualisieren, kann ich die GUI nicht wirklich aktualisieren, wenn ich keinen Toggle Breakpoint in einer bestimmten Zeile platziere.JavaFX aktualisiert Grafik nur mit Debug und Haltepunkten
Wenn ich meine Clients nicht im Debug-Modus starte, scheinen die Grafiken das Update nicht zu machen, sie erscheinen einfach und nichts passiert mehr.
Auch wenn ich den Schalter nicht in eine bestimmte Zeile meines Codes, und ich lege es in eine andere Zeile (tiefer in der Methode Aufrufsequenz), passiert nichts. Also hört der Client-Thread nicht auf; als ob es nicht die Methode ruft, die es mit dem Haltepunkt tut. Ich starte meine Klienten alle in der gleichen Maschine und nur eine (mit Toggle Break Points) wird aktualisiert.
Jetzt zeige ich Ihnen meinen Code.
javafx beginnt hier in einer cla genannt RMIGUIView.java
@Override
public synchronized void run() {
waiting = true;
pause();
guiDisplayer = new GUIDisplayer();
(new Thread(() -> guiDisplayer.startGUI())).start();
waiting = false;
do {
state.acceptView(this);
} while(!endGame);
}
dann mache ich den Start der GUI (während des Starts Methode, die ich von der Bühne auf dem Controller speichern, wie es hier vorgeschlagen wirdPassing Parameters JavaFX FXML
public class GUIDisplayer extends Application {
private StartTurnState currentState;
private Stage stage;
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);
}
public static void startGUI() {
Application.launch();
} }
nach dem Start des gui ich in meinem RMIGUIView.java zurückkehren, und ich tue dies
@Override
public void visit(StartTurnState currentState) {
GUIController guiController = new GUIController();
guiController.updateGUI(currentState);
}
und hier ist meine Controller-Klasse, wo ich die Breakpoint setzen, wenn ich somethig (lesen Sie bitte in der Klasse Kommentare) passieren soll
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);
} }
Ich hoffe, Sie verstehen meine Frage. Ich werde meine Frage bearbeiten, wenn Sie etwas nicht verstehen. Ich habe so etwas bei Stackoverflow nicht gefunden.
Vielen Dank im Voraus für Ihre Hilfe.
EDIT: Ich habe tryed den Code neu zu schreiben, wie durch James_D dies ist mein neuer Aufruf der Update GUI vorgeschlagen.
@Override
public void visit(StartTurnState currentState) {
guiDisplayer.setState(currentState);
Platform.runLater(()-> guiDisplayer.run());
}
Ich habe modifiziert auch die GUIDisplayer Klasse
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);
} }
Die runLater Methodenaufruf ignoriert zu werden scheint, vielleicht habe ich in diesem Fall bin durch die javadoc descibed
Wenn diese Methode ist Nachdem die JavaFX-Laufzeit heruntergefahren wurde, wird der Aufruf ignoriert: Das Runnable wird nicht ausgeführt und es wird keine Ausnahme ausgelöst.
Wenn ich den runLater entferne und toggle brackpoints hinzufüge, kann ich die GUI noch ändern.
Ihr Brettspiel muss schnell aktualisieren? – GOXR3PLUS
Es muss zu Beginn jedes Spielzuges aktualisiert werden, mindestens alle 5 Minuten. – axoaxel
Generell in Ihrem Code folgen Sie dieser Anweisung: Vermeiden Sie javaFX SceneGraph außerhalb des javaFX-Threads zu ändern (wenn Sie nicht sicher sind, in welchem Thread Sie platform.isFxApplicationThread verwenden()) Andernfalls müssen Sie Platform.runLater() verwenden, aber nicht übermäßig verwenden, da die App verzögert wird. Um Code in anderen Threads auszuführen, überprüfen Sie http://docs.oracle.com/javafx/2/threads/jfxpub-threads. htm. Ich fragte, wie schnell es aktualisiert, falls Sie javaFX AnimationTimer für die schnelle Aktualisierung verwenden wollten http://download.java.net/jdk8/jfxdocs/javafx/animation/AnimationTimer.html – GOXR3PLUS