Your code generates a ClassCastException
in the onFinished
handler defined in getBackPreviousScene()
, because the source of the event is the PauseTransition
, which is not a Node
. It doesn't have a Scene
or access to one.
First, using the source of the event in general is not a very good way to access the scene. Instead, you can simply call getScene()
on any of the injected nodes in the controller. E.g.:
public class FXMLDocumentController implements Initializable {
@FXML Label itemCouner;
public void frize(Event event) throws IOException {
FXMLLoader watingLoader = new FXMLLoader();
watingLoader.setLocation(getClass().getResource("/FXMLfiles/wating.fxml"));
Parent watingParent = watingLoader.load();
Scene watingScene = new Scene(watingParent);
Stage watingStage = (Stage)itemCouner.getScene().getWindow();
watingStage.setScene(watingScene);
// watingStage.show();
}
@Override
public void initialize(URL url, ResourceBundle rb) {
Random myRand = new Random();
int holdingFrizes = myRand.nextInt(2);
}
}
Note also that if you're getting the window containing a scene containing a node on which an event occurred, that window must necessarily already be showing, so there's no point at all in calling
watingStage.show();
in the code above. You could do the same in your WatingController
by injecting some node into the controller.
Second, the WatingController
seems to be the wrong place to control how long the UI declared in the FXML is displayed. This should be the responsibility of the code that displays it, which in this case is the frize()
method in the FXMLDocumentController
class. In particular, this makes it impossible to load the FXML ahead of time and display it later, because after six seconds calling getScene().getWindow()
would throw a null pointer exception.
So, e.g., you could do:
public class FXMLDocumentController implements Initializable {
@FXML Label itemCouner;
public void frize(Event event) throws IOException {
FXMLLoader watingLoader = new FXMLLoader();
watingLoader.setLocation(getClass().getResource("/FXMLfiles/wating.fxml"));
Parent watingParent = watingLoader.load();
Scene watingScene = new Scene(watingParent);
Scene currentScene = itemCouner.getScene();
Stage stage = (Stage) currentScene.getWindow();
stage.setScene(watingScene);
PauseTransition pause = new PauseTransition(Duration.seconds(6));
pause.setOnFinished(e -> stage.setScene(currentScene));
pause.play();
}
@Override
public void initialize(URL url, ResourceBundle rb) {
}
}
And then the code in your WatingController
can all be removed.
Finally, note that in your example there seems to be no need at all to create new scenes. Just replace the root of the existing scene:
public class FXMLDocumentController implements Initializable {
@FXML Label itemCouner;
public void frize(Event event) throws IOException {
FXMLLoader watingLoader = new FXMLLoader();
watingLoader.setLocation(getClass().getResource("/FXMLfiles/wating.fxml"));
Parent watingParent = watingLoader.load();
Scene currentScene = itemCouner.getScene();
Parent currentRoot = currentScene.getRoot();
currentScene.setRoot(watingParent);
PauseTransition pause = new PauseTransition(Duration.seconds(6));
pause.setOnFinished(e -> currentScene.setRoot(currentRoot));
pause.play();
}
@Override
public void initialize(URL url, ResourceBundle rb) {
}
}
Complete example:
primary.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Button?>
<?import javafx.geometry.Insets?>
<VBox alignment="CENTER" spacing="20.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.jamesd.examples.tempscene.PrimaryController">
<children>
<Button fx:id="showTempButton" text="Show Temporary View" onAction="#showTemp"/>
</children>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
</VBox>
PrimaryController.java:
package org.jamesd.examples.tempscene;
import java.io.IOException;
import javafx.animation.PauseTransition;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.util.Duration;
public class PrimaryController {
@FXML
private Button showTempButton ;
@FXML
private void showTemp() throws IOException {
Scene currentScene = showTempButton.getScene();
Parent currentRoot = currentScene.getRoot();
FXMLLoader loader = new FXMLLoader(getClass().getResource("temp.fxml"));
Parent tempRoot = loader.load();
currentScene.setRoot(tempRoot);
PauseTransition pause = new PauseTransition(Duration.seconds(2));
pause.setOnFinished(e -> currentScene.setRoot(currentRoot));
pause.play();
}
}
temp.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Button?>
<?import javafx.geometry.Insets?>
<VBox alignment="CENTER" spacing="20.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" >
<children>
<Label text="Temporary View" />
</children>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
</VBox>
App.java:
package org.jamesd.examples.tempscene;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class App extends Application {
private static Scene scene;
@Override
public void start(Stage stage) throws IOException {
scene = new Scene(FXMLLoader.load(getClass().getResource("primary.fxml")), 640, 480);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}