Exception javafx Thread -> caused by removing children while in EventHandler

  • Themenstarter Themenstarter Gelöschtes Mitglied 65838
  • Beginndatum Beginndatum
G

Gelöschtes Mitglied 65838

Gast
Es gibt einen Menubutton mit dem Menu Item "Main Menue"
dieser ruft diese funktion auf
Java:
    private static StackPane rootStackPane;
    private static DeckStackPane deckStackPane;
    private static MainMenueStackPane mainMenue;
    private static PlayStackPane playStackPane;
    private static ShopStackPane shopStackPane;

 .... 


returnToMainMenu.setOnAction(event->{
            GuiGraphicsFunctionForAll.setTheMainScene();
        });
// rootstackpane = leere stackpane wo man die Panes drauf austauscht
// mainmenue = eine extends StackPane Objekt das schon eine vorgefertigte GUI ist
GuiGraphicsFunctionForAll Class
    private static void deleteStackPaneItem() {
        rootStackPane.getChildren().removeAll(rootStackPane.getChildren());
    }
    public static void setTheMainScene() {
        deleteStackPaneItem();
        rootStackPane.getChildren().add(GuiGraphicsFunctionForAll.mainMenue);
    }

der Eventhandler funktioniert und auch alle Funktionen das Problem ist NACHDEM der Eventhandler fertig ist und ALLES richtig gemacht hat
kommt diese exception die zwar keinen Einfluss auf das Programm hat aber es ist nervig dass sie da ist

Java:
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
    at java.base/java.util.Objects.requireNonNull(Objects.java:208)
    at javafx.controls/javafx.scene.control.skin.MenuButtonSkinBase.lambda$new$7(MenuButtonSkinBase.java:206)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
    at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
    at java.base/java.lang.Thread.run(Thread.java:832)

Wie schaffe ich es dass die Exception weg geht
VERDACHT:
Während der Event Dispatch Chain
Möchte der Menubutton das Event zurück an seine Scene schicken jedoch hat er diese Scene dann nicht mehr
jedoch event.consume() hat keine Auswirkung auf das Ergebnis
 
Zuletzt bearbeitet von einem Moderator:
Wenn Du JavaFX 12 verwendest, dann ist es möglich.

Generell ist der Ratschlag, immer auf die aktuelle Version zu setzen (also Java 15 und JavaFX 15). Oder alternativ die LTS Version (11), wobei da die Patche nur gegen Geld zur Verfügung gestellt werden von Gluon. Daher bringt das nicht viel.
 
ich benutze openjfx 15.0.1
udn bei eclipse steht das java 15 verwendet wird
 
das ist die Main klasse

[CODE lang="java" title="LauncherOfMainMenueWithMain"]package application;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class LauncherOfMainMenueWithMain extends Application {

public GuiGraphicsFunctionForAll functionsGUIforAll;
public void start(Stage primaryStage) throws Exception {
functionsGUIforAll = new GuiGraphicsFunctionForAll();
Scene scene = new Scene(GuiGraphicsFunctionForAll.getRootStackPane());
primaryStage.setFullScreen(true);
primaryStage.setScene(scene);
primaryStage.show();
}
}[/CODE]

diese Funktionen Werden gebraucht in diesem fall geht es um "setTheMainScene"
und deleteStackPaneItem

[CODE lang="java" title="GuiGraphicsFunctionForAll"]package application;

import javafx.scene.layout.StackPane;

public class GuiGraphicsFunctionForAll {
private static StackPane rootStackPane;
private static DeckStackPane deckStackPane;
// private static MainMenueStackPane mainMenue;
// private static PlayStackPane playStackPane;
// private static ShopStackPane shopStackPane;


public GuiGraphicsFunctionForAll() throws Exception {
rootStackPane = new StackPane();
deckStackPane = new DeckStackPane();
playStackPane = new PlayStackPane();
shopStackPane = new ShopStackPane();
GuiGraphicsFunctionForAll.mainMenue = new MainMenueStackPane();
rootStackPane.getChildren().add(mainMenue);
setTheMainScene();
}
public static StackPane getRootStackPane() {
return rootStackPane;
}
private static void deleteStackPaneItem() {
rootStackPane.getChildren().removeAll(rootStackPane.getChildren());
}
public static void exitProgramm() {
System.exit(0);
// disconnects from server
}
public static void setTheMainScene() {
deleteStackPaneItem();
rootStackPane.getChildren().add(GuiGraphicsFunctionForAll.mainMenue);
}
// public static void setTheDeckScene() {
// deleteStackPaneItem();
// rootStackPane.getChildren().add(deckStackPane);
// }
// public static void setThePlayScene() {
// rootStackPane.getChildren().add(playStackPane);
// }
// public static void setTheShopScene() {
// rootStackPane.getChildren().add(shopStackPane);
// }
}
[/CODE]

erstellt die deck szene hier passiert der fehler bei returnToMainMenu beim action event
es geht erfolgreich zurück auf die hauptseite aber nachdem das event ausgelöst und erfolgreich wurde kommt die exception
[CODE lang="java" title="DeckStackPane"]package application;

import java.io.File;

import javafx.geometry.Rectangle2D;
import javafx.scene.control.MenuButton;
import javafx.scene.control.MenuItem;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Rectangle;
import javafx.stage.Screen;

public class DeckStackPane extends StackPane {
private MenuItem returnToMainMenu = new MenuItem("Main Menue");
private MenuItem returnToPlayMenu = new MenuItem("Play");
private MenuItem returnToShopMenu= new MenuItem("Shop");
private MenuItem returnToExitMenu = new MenuItem("Exit");
private MenuButton navigationButton = new MenuButton("Navigation", null , returnToMainMenu,returnToPlayMenu, returnToShopMenu, returnToExitMenu);
// MenuButton Modify Decks -> items
private MenuItem createDeck = new MenuItem("Create Deck");
private MenuItem loadDeck = new MenuItem("Load");
private MenuItem saveDeck = new MenuItem("Save");
private MenuItem deleteDeck = new MenuItem("Delete");
private MenuButton modifyDeckButton = new MenuButton("Modify Deck", null ,saveDeck,createDeck, loadDeck, deleteDeck);
// MenuButton SearchButton -> items
private MenuItem searchCreatures = new MenuItem("Creatures");
private MenuItem searchCasts = new MenuItem("Casts");
private MenuItem searchCommander = new MenuItem("Commander");
private MenuButton searchCardsButton = new MenuButton("Search for Cards", null ,searchCreatures,searchCasts,searchCommander);

public DeckStackPane () throws Exception{
// this.getStylesheets().add(new File("styleDeck.css").toURI().toURL().toExternalForm());
// ImageView imageV = new ImageView(new Image("mainMenueWallPaper.jpg"));
// this.getChildren().add(imageV);

BorderPane bpMain = new BorderPane();

HBox navigationMenue = new HBox();
// java - get screen size using the Toolkit class
//set Stage boundaries to visible bounds of the main screen
Pane pictureInfo = new Pane();
pictureInfo.setMaxSize(40, 40);
ImageView imageV1 = new ImageView(new Image("theorie.jpg"));
pictureInfo.getChildren().add(imageV1);
HBox infoLeft = new HBox();

infoLeft.getChildren().add(pictureInfo);
bpMain.setLeft(infoLeft);
bpMain.setTop(navigationMenue);
this.getChildren().add(bpMain);

// add the Top bar Menu
navigationMenue.getChildren().addAll(navigationButton,modifyDeckButton,searchCardsButton);
// calls all addEventHandlerMethods
this.addEventHandlerNavigation();
this.addEventHandlerModifyDeckButton();
this.addEventHandlerSearchCardsButton();
}
private void addEventHandlerNavigation() {
// EventHandler -> MenuButton Navigation Items
returnToMainMenu.setOnAction(event->{
GuiGraphicsFunctionForAll.setTheMainScene();
});
returnToPlayMenu.setOnAction(event->{
// GuiGraphicsFunctionForAll.setThePlayScene();
});
returnToShopMenu.setOnAction(event->{
// GuiGraphicsFunctionForAll.setTheShopScene();

});
returnToExitMenu.setOnAction(event->{
GuiGraphicsFunctionForAll.exitProgramm();
});
}
private void addEventHandlerModifyDeckButton() {
loadDeck.setOnAction(event->{

});
saveDeck.setOnAction(event->{

});
deleteDeck.setOnAction(event->{

});
createDeck.setOnAction(event->{

});
}
private void addEventHandlerSearchCardsButton() {
searchCreatures.setOnAction(event->{

});
searchCasts.setOnAction(event->{

});
searchCommander.setOnAction(event->{

});
}
}


[/CODE]
[CODE lang="java" title="MainMenueStackPane"]package application;

import java.io.File;
import java.net.MalformedURLException;

import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;

public class MainMenueStackPane extends StackPane {
private Button playButton = new Button("Play");
private Button deckButton = new Button("Deck");
private Button shopButton = new Button("Shop");
private Button closeButton = new Button("Exit");
public MainMenueStackPane() throws Exception {
// this.getStylesheets().add(new File("style.css").toURI().toURL().toExternalForm());
// 1. Set Background Image
// ImageView imageV = new ImageView(new Image("mainMenueWallPaper.jpg"));
// this.getChildren().add(imageV);
// gp necessary for center Vbox -> idk why
GridPane gp = new GridPane();
VBox menueBox = new VBox();
menueBox.getChildren().addAll(playButton, deckButton,shopButton,closeButton);
menueBox.setAlignment(Pos.CENTER);
menueBox.setSpacing(10);
VBox.setMargin(closeButton, new Insets(30));
gp.getChildren().add(menueBox);
gp.setAlignment(Pos.CENTER);
this.getChildren().add(gp);
this.setAlignment(gp, Pos.CENTER);
this.addEventHandlerMenu();
// 1. EventHandler: closeButton -> close Program (System.exit(0)) + disconnect acc

}
private void addEventHandlerMenu() {
closeButton.setOnAction(event->{
GuiGraphicsFunctionForAll.exitProgramm();
});
playButton.setOnAction(event->{
GuiGraphicsFunctionForAll.setTheMainScene();;
});
// opens the deckMenue Object GUI
shopButton.setOnAction(event->{

});
deckButton.setOnAction(event->{
// GuiGraphicsFunctionForAll.setTheDeckScene();
});
}
}
[/CODE]

Ich weis es ist viel code aber ich weis nicht wie ich es sonst machen sollte...
wenn man die 3 klassen einfügt sollte es funktionieren und Sie könnten es selber ausprobieren


das aktuelle problem ist in der Klasse DeckStackPane der Action Handler
für das Menu Objekt returnToMainMenu
es führt den action EventHandler aus und geht dann in die GuiFunctionsForAll rein
und führt dann setTheMainScene aus das ist auch noch erfolgreich
und DANN kommt die Exception


Bestimmt kommt das Kommentar dass der Code furchtbar ist xDDDD
 
Erst einmal danke für den Code. Im Augenblick kann ich es nicht ausprobieren, aber ich versuche später die Zeit dafür zu finden. Aber evtl. kommt mir auch jemand anderes zuvor.
Bestimmt kommt das Kommentar dass der Code furchtbar ist xDDDD
Also so auf Anhieb ist mir noch nichts so schlimmes aufgefallen, aber ich bin es auch noch nicht im Detail durchgegangen.

Generell sind das dann aber auch immer Vorschläge, wie es besser gehen könnte und nur als Hilfestellung gedacht. Und egal wie ggf. Fehler bezeichnet werden (Ich neige z.B. dazu, Code Abschnitte als Quatsch oder so zu bezeichnen), dann ist das nie als Beleidigung oder ähnliches gedacht.

Das einfach nur als kleine Zwischenmeldung.

PS: Sollte morgen Abend noch nichts hilfreiches gekommen sein, einfach kurz per Antwort hier erinnern 🙂
 
Erst einmal danke für den Code. Im Augenblick kann ich es nicht ausprobieren, aber ich versuche später die Zeit dafür zu finden. Aber evtl. kommt mir auch jemand anderes zuvor.

Also so auf Anhieb ist mir noch nichts so schlimmes aufgefallen, aber ich bin es auch noch nicht im Detail durchgegangen.

Generell sind das dann aber auch immer Vorschläge, wie es besser gehen könnte und nur als Hilfestellung gedacht. Und egal wie ggf. Fehler bezeichnet werden (Ich neige z.B. dazu, Code Abschnitte als Quatsch oder so zu bezeichnen), dann ist das nie als Beleidigung oder ähnliches gedacht.

Das einfach nur als kleine Zwischenmeldung.

PS: Sollte morgen Abend noch nichts hilfreiches gekommen sein, einfach kurz per Antwort hier erinnern 🙂
Dankeschön für deine Hilfe 😀

Falls etwas nicht passen sollte mit dem code werde ich noch einmal einen code erstellen der sicher funktioniert
 
Keine Ahnung, ob das hilft, aber ich würde als erstes mal das
rootStackPane.getChildren().removeAll(rootStackPane.getChildren());
durch
rootStackPane.getChildren().clear();
ersetzen.
Wenn du die selbe (also identische Referenz, nicht nur Inhaltlich gleich) Liste verwendest, gibt es generell gern mal die abstruse Fehler. Und clear ist allemal sauberer.
 
Keine Ahnung, ob das hilft, aber ich würde als erstes mal das
rootStackPane.getChildren().removeAll(rootStackPane.getChildren());
durch
rootStackPane.getChildren().clear();
ersetzen.
Wenn du die selbe (also identische Referenz, nicht nur Inhaltlich gleich) Liste verwendest, gibt es generell gern mal die abstruse Fehler. Und clear ist allemal sauberer.
Vielen Dank
ich habe es ersetzt
der Code ist jetzt schicker

Fehler kommt immer noch 😀
 
ok hab es gelöst auch wenn es absolut KEINEN SINN macht
this.navigationButton.hide();
bevor die root stackpane geändert wird KEINE AHNUNG WARUM
aber wenns funktioniert nicht mehr anfassen

der bug wurde also nicht gefixed...

mein code ist der lebende beweis 😀
 
Zuletzt bearbeitet von einem Moderator:
Zumindest mit obigen Code kann ich den Fehler nicht reproduzieren, das läuft problemlos unter JavaFX 11, 12 und 15 unter macOS.
 
Zumindest mit obigen Code kann ich den Fehler nicht reproduzieren, das läuft problemlos unter JavaFX 11, 12 und 15 unter macOS.
der code funktioniert auch, nur wenn du auf deck klickst und dann auf navigation button klickst um zu main menu zu kommen kommt die exception da is das problem was nicht sein darf
 
Ich hab alle Buttons in jeder beliebigen Reihenfolge X mal gedrückt, bei mir fliegt da keine Exception – allerdings gibt es auch keinen "navigation button", meinst du den "Play"-Button?

EDIT: nachdem ich ein paar der auskommentierten Sachen wieder hinzugefügt hab, kommt man über "Deck" jetzt zu anderem Content, und über "Main Menue" auch wieder zurück – ne Exception fliegt aber auch dabei nicht.
 
der navigation button sollte links oben sein nachdem man auf deck geklickt hat , jedoch wird der nicht automatisch berechnet aus irgend einem grund, getestet wurde es für die auflösugn 1920 . 1080
 
Ich hab alle Buttons in jeder beliebigen Reihenfolge X mal gedrückt, bei mir fliegt da keine Exception – allerdings gibt es auch keinen "navigation button", meinst du den "Play"-Button?

EDIT: nachdem ich ein paar der auskommentierten Sachen wieder hinzugefügt hab, kommt man über "Deck" jetzt zu anderem Content, und über "Main Menue" auch wieder zurück – ne Exception fliegt aber auch dabei nicht.
vllt ist es ein windows bzw eclipse problem ich habe es noch nicht auf meinem linux laptop ausprobiert , mac besitze ich nicht
 
openjfx-15.0.1_windows-x64_bin-sdk
das hab ich als javafx library hinzugefügt
 
Jetzt konnte ich ihn reproduzieren, das ist ein Bug im JavaFX-Code (wenn sie es denn als Bug anstehen).

Ein weniger "hacky" Fix wäre, innerhalb von setTheMainScene ein Platform.runLater zu benutzen. Alternativ könntest du für verschiedene Szenen in dem Programm auch einfach verschiedene Scenes nutzen, anstatt Stackpanes auszutauschen, das dürfte den Fehler auch beheben 🙂
 
Jetzt konnte ich ihn reproduzieren, das ist ein Bug im JavaFX-Code (wenn sie es denn als Bug anstehen).

Ein weniger "hacky" Fix wäre, innerhalb von setTheMainScene ein Platform.runLater zu benutzen. Alternativ könntest du für verschiedene Szenen in dem Programm auch einfach verschiedene Scenes nutzen, anstatt Stackpanes auszutauschen, das dürfte den Fehler auch beheben 🙂
ich werde das mal ausprobieren
habe auch eine lösung gefunden auch wenn sie keinen sinn für mich ergibt
ich mach beim menu button .hide() bevor ich tausche und der fehler ist dann weg WIESO AUCH IMMER
 
habe auch eine lösung gefunden auch wenn sie keinen sinn für mich ergibt
ich mach beim menu button .hide() bevor ich tausche und der fehler ist dann weg WIESO AUCH IMMER
Um Mal eben das Problem zu beschreiben:


Beim Schließen des Menüs (was automatisch nach dem Klick auf ein Item passiert) werden die Mnemonics für das jeweilige Menü aus der Szene entfernt. Dabei wird natürlich die Scene benötigt, in der das Menü grad angezeigt wird.

In deinem fehlerhaften Code entfernst du das Menü allerdings aus der Szene, bevor das Menü geschlossen wird – wenn die Mnemonics dann aus der Szene entfernt werden sollen, ist diese null, und es fliegt der NPE.

Wenn du das Menü aber "versteckst", werden dabei die Mnemonics aufgeräumt, und zwar bevor es aus der Szene entfernt wird – die Szene ist dabei dann noch nicht null.

Was ähnliches passiert, wenn du Platform.runLater benutzt: das entfernen des Menüs aus der Szene wird damit "nach hinten" geschoben, das Menü kann also normal geschlossen und die Mnemonics entfernt werden, bevor das Menü keine Szene mehr hat.




Ob das wirklich ein Bug ist, ist schwer zu sagen; um die Mnemonics aufzuräumen, braucht man die Szene, sonst hat man da memory Leaks und ins nichts führende Mnemonics, die dann Folge-Fehler auslösen könnten. Könnte man Fixen, der Fix bringt aber u.U. weitere Problem mit sich, ist potentiell leichter, ein Löschen des Menüs bevor es geschlossen ist als "darf man nicht" zu spezifizieren.



EDIT: das erste reproduzieren scheiterte bei mir daran, dass ich's nicht im Vollbild laufen hatte (um den Debugger nebenbei zu benutzen...), und in der "kleinen" Ansicht tritt der Fehler einfach nicht auf...
 
Um Mal eben das Problem zu beschreiben:


Beim Schließen des Menüs (was automatisch nach dem Klick auf ein Item passiert) werden die Mnemonics für das jeweilige Menü aus der Szene entfernt. Dabei wird natürlich die Scene benötigt, in der das Menü grad angezeigt wird.

In deinem fehlerhaften Code entfernst du das Menü allerdings aus der Szene, bevor das Menü geschlossen wird – wenn die Mnemonics dann aus der Szene entfernt werden sollen, ist diese null, und es fliegt der NPE.

Wenn du das Menü aber "versteckst", werden dabei die Mnemonics aufgeräumt, und zwar bevor es aus der Szene entfernt wird – die Szene ist dabei dann noch nicht null.

Was ähnliches passiert, wenn du Platform.runLater benutzt: das entfernen des Menüs aus der Szene wird damit "nach hinten" geschoben, das Menü kann also normal geschlossen und die Mnemonics entfernt werden, bevor das Menü keine Szene mehr hat.




Ob das wirklich ein Bug ist, ist schwer zu sagen; um die Mnemonics aufzuräumen, braucht man die Szene, sonst hat man da memory Leaks und ins nichts führende Mnemonics, die dann Folge-Fehler auslösen könnten. Könnte man Fixen, der Fix bringt aber u.U. weitere Problem mit sich, ist potentiell leichter, ein Löschen des Menüs bevor es geschlossen ist als "darf man nicht" zu spezifizieren.



EDIT: das erste reproduzieren scheiterte bei mir daran, dass ich's nicht im Vollbild laufen hatte (um den Debugger nebenbei zu benutzen...), und in der "kleinen" Ansicht tritt der Fehler einfach nicht auf...
was müsste amn platform.runlater übergeben dass es dann funnktioniert
ohne zeitverlust
 
Alles, was in der Methode steht.

das “later” dabei meint kein “spürbares Später“ 🙂
übrigens weil cih dein auto kommentar sehe mit dem code, ist denn mein code lesbar 😀
ich mag kommentare nicht wirklich der code sollte sich selbst erklären soweit wie möglich
 
@mrBrown wenn du denkst, dass ein Fehler in JavaFX sein könnte, könntest du das auf GitHub ja als Issue erfassen.
Alternativ: Unsere Firma hat einen Wartungsvertrag mit Gluon - ich könnte denen auch einfach eine Mail schicken, wenn du mir ein lauffähiges Code-Snipped schickst (PN oder so)...

Nur so als reichlich später Input von mir an dieser Stelle.
 

Neue Themen


Zurück
Oben