web-dev-qa-db-fra.com

Comment changer de scène dans JavaFX

J'ai regardé sur de nombreuses pages pour essayer de savoir comment changer de scène, mais je n'ai pas réussi.

J'ai une calculatrice et mon objectif est de sélectionner une option de menu pour changer de calculatrice (c.-à-d. De base et scientifique). En ce moment, je suis en train de tester, voici donc mon code pertinent pour cette question (j'utilise Scene Builder):

@FXML private MenuItem basic;
@FXML private MenuItem testSwitch;


public static void main(String[] args)
{
    Application.launch( args );

}
@Override
public void start(Stage primaryStage) throws Exception
{
   Parent pane = FXMLLoader.load(
           getClass().getResource( "calculator.fxml" ) );

   Scene scene = new Scene( pane );
   primaryStage.setScene(scene);
   primaryStage.setTitle( "Calculator" );
   primaryStage.show();

}
@FXML
public void handleMenuOption(ActionEvent e) 
{
    if(e.getSource()==basic)
    {
        changeScene("calculator.fxml");
    }
    else if(e.getSource()==testSwitch)
    {
        changeScene("TestSwitch.fxml");
    }
}
public void changeScene(String fxml) 
{
    //this prints out
    System.out.println(fxml);
}

EDIT J'ai déjà essayé pas mal de choses. Quoi qu'il arrive, je reçois toujours cette exception NullPointerException. J'ai l'impression que cela peut avoir à voir avec l'installation de quelque chose dans le créateur de scène, mais je n'ai tout simplement pas été en mesure de trouver une réponse.

Exception in thread "JavaFX Application Thread" Java.lang.RuntimeException: Java.lang.reflect.InvocationTargetException
at javafx.fxml.FXMLLoader$MethodHandler.invoke(Unknown Source)
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(Unknown Source)
at com.Sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source)
at com.Sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
at com.Sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
at com.Sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
at com.Sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
at com.Sun.javafx.event.EventUtil.fireEventImpl(Unknown Source)
at com.Sun.javafx.event.EventUtil.fireEvent(Unknown Source)
at javafx.event.Event.fireEvent(Unknown Source)
at javafx.scene.control.MenuItem.fire(Unknown Source)
at com.Sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.doSelect(Unknown Source)
at com.Sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.lambda$createChildren$343(Unknown Source)
at com.Sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(Unknown Source)
at com.Sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source)
at com.Sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
at com.Sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
at com.Sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(Unknown Source)
at com.Sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
at com.Sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
at com.Sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
at com.Sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
at com.Sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
at com.Sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
at com.Sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
at com.Sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
at com.Sun.javafx.event.EventUtil.fireEventImpl(Unknown Source)
at com.Sun.javafx.event.EventUtil.fireEvent(Unknown Source)
at javafx.event.Event.fireEvent(Unknown Source)
at javafx.scene.Scene$MouseHandler.process(Unknown Source)
at javafx.scene.Scene$MouseHandler.access$1500(Unknown Source)
at javafx.scene.Scene.impl_processMouseEvent(Unknown Source)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Unknown Source)
at com.Sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source)
at com.Sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source)
at Java.security.AccessController.doPrivileged(Native Method)
at com.Sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(Unknown Source)
at com.Sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(Unknown Source)
at    com.Sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(Unknown Source)
at com.Sun.glass.ui.View.handleMouseEvent(Unknown Source)
at com.Sun.glass.ui.View.notifyMouse(Unknown Source)
at com.Sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.Sun.glass.ui.win.WinApplication.lambda$null$148(Unknown Source)
at Java.lang.Thread.run(Unknown Source)
Caused by: Java.lang.reflect.InvocationTargetException
at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at Sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at Java.lang.reflect.Method.invoke(Unknown Source)
at Sun.reflect.misc.Trampoline.invoke(Unknown Source)
at Sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at Sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at Java.lang.reflect.Method.invoke(Unknown Source)
at Sun.reflect.misc.MethodUtil.invoke(Unknown Source)
... 44 more
Caused by: Java.lang.NullPointerException
at CalculatorMain.changeScene(CalculatorMain.Java:75)
at CalculatorMain.handleMenuOption(CalculatorMain.Java:64)
... 53 more




at CalculatorMain.changeScene(CalculatorMain.Java:75)
This is at:stage . getScene() . setRoot(pane);


at CalculatorMain.handleMenuOption(CalculatorMain.Java:64)
This is at:changeScene ("TestSwitch.fxml");

CODE DE TRAVAIL:

J'ai joué avec les suggestions ci-dessous et utilisé ce code pour le faire fonctionner:

private Stage stage;

public static void main(String[] args)
{
    Application.launch( args );
}

@Override
public void start(Stage primaryStage) throws Exception
{
    this.stage = primaryStage;
    FXMLLoader loader = new FXMLLoader(getClass()
            .getResource("calculator.fxml"));
    Parent root = (Parent)loader.load();
    BasicCalculatorView controller = (BasicCalculatorView)loader.getController();
    controller.setModel(new BasicCalculatorModelTest(controller));
    controller.setLogic(this);
    primaryStage.setTitle("Calculator");
    primaryStage.setScene(new Scene(root));
    primaryStage.show();
}

public void switchScene(String fxmlFile)
{

    FXMLLoader loader = new FXMLLoader(getClass()
            .getResource(fxmlFile));
    Parent root;
    try 
    {
        root = (Parent)loader.load();
        if(fxmlFile.equals("calculator.fxml"))
        {
            BasicCalculatorView controller = (BasicCalculatorView)loader.getController();
            controller.setModel(new BasicCalculatorModelTest(controller));
            controller.setLogic(this);
        }
        else if(fxmlFile.equals("TestSwitch.fxml"))
        {
            TestSwitch controller = (TestSwitch)loader.getController();
            controller.setLogic(this);
        }
        this.stage.setScene(new Scene(root));
    } 
    catch (IOException e)
    {
        e.printStackTrace();
    }

}
4
Megan

J'ai écrit ce contrôleur pour garder une trace des différents scenégraphes.

public class ScreenController {
    private HashMap<String, Pane> screenMap = new HashMap<>();
    private Scene main;

    public ScreenController(Scene main) {
        this.main = main;
    }

    protected void addScreen(String name, Pane pane){
         screenMap.put(name, pane);
    }

    protected void removeScreen(String name){
        screenMap.remove(name);
    }

    protected void activate(String name){
        main.setRoot( screenMap.get(name) );
    }
}

Donc je peux écrire:

ScreenController screenController = new ScreenController(scene);
screenController.add("calculator", FXMLLoader.load(getClass().getResource( "calculator.fxml" )));
screenController.add("testSwitch", FXMLLoader.load(getClass().getResource( "TestSwitch.fxml" )));
screenController.activate("calculator");

Il s'agissait d'une solution de contournement pour une application en plein écran, dans laquelle la transition en plein écran MacOS était affichée chaque fois qu'une scène changeait de scène.

6
MrEbbinghaus

Au lieu de changer Scenes, basculez un noeud racine sur Scene déjà existant 

3
Eugene Ryzhikov

Si vous souhaitez modifier la scène, procédez comme suit (notez que la scène est membre de l'application):

private Stage primaryStage;

@Override
public void start(Stage primaryStage) throws Exception {
    this.primaryStage = primaryStage;
    ...
}

public void changeScene(String fxml){
    Parent pane = FXMLLoader.load(
           getClass().getResource(fxml));

   Scene scene = new Scene( pane );
   primaryStage.setScene(scene);
}

Cependant, comme l'a déjà souligné @Eugene_Ryzhikov, il est préférable de modifier simplement le contenu racine de la scène existante:

public void changeScene(String fxml){
    Parent pane = FXMLLoader.load(
           getClass().getResource(fxml));

   primaryStage.getScene().setRoot(pane);
}
1
hotzst

Il semble que OP l'ait déjà résolu, mais comme il est toujours ouvert et non résolu, je vais partager une solution trouvée dans une autre réponse. N'oubliez pas de choisir une réponse correcte ou de publier votre propre solution lorsqu'une question est résolue, cela aide les personnes qui se trouvent dans le même problème à l'avenir (comme je l'ai fait).

Je viens de courir dans le même problème et cette réponse résolu mon problème parfaitement tout en étant court et propre.

@FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
label.setText("Hello World!");
//Here I want to swap the screen!

Stage stageTheEventSourceNodeBelongs = (Stage) ((Node)event.getSource()).getScene().getWindow();
// OR
Stage stageTheLabelBelongs = (Stage) label.getScene().getWindow();
// these two of them return the same stage
// Swap screen
stage.setScene(new Scene(new Pane()));

}

PS: Pensez à vérifier la réponse originale et à la voter. Le gars mérite ...

PPS.: Je ne suis pas sûr de simplement copier une réponse, mais plutôt de partager le lien avec un commentaire, mais comme cela n’a pas encore de réponse correcte, j’ai décidé de le faire pour plus de visibilité.

0
BarriaKarl
TypesController.Java
package todoapp;
import Java.io.IOException;
import Java.net.URL;
import Java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.stage.Stage;

public class TypesController implements Initializable {
@FXML
private CheckBox c1;
@FXML
private CheckBox c2;
public void clicked(ActionEvent e) throws IOException {
Parent home_page_parent =FXMLLoader.load(getClass().getResource("AddDcuFXML.fxml"));
Scene home_page_scene = new Scene(home_page_parent);
Stage app_stage = (Stage) ((Node) e.getSource()).getScene().getWindow();
app_stage.hide(); //optional
app_stage.setScene(home_page_scene);
app_stage.show();
}
public void clicked1(ActionEvent e) throws IOException {
Parent home_page_parent =   FXMLLoader.load(getClass().getResource("AddDcuFXML.fxml"));
    Scene home_page_scene = new Scene(home_page_parent);
    Stage app_stage = (Stage) ((Node)e.getSource()).getScene().getWindow();
   app_stage.hide(); //optional
   app_stage.setScene(home_page_scene);
   app_stage.show();
   }
  @Override
  public void initialize(URL arg0, ResourceBundle arg1) {
 // TODO Auto-generated method stub
  } }
0
lakshmi