2016-05-13 2 views
2

J'ai regardé sur plusieurs pages pour essayer de savoir comment changer de scène mais je n'ai pas réussi.Comment changer de scène en JavaFX

J'ai une calculatrice et mon objectif est de sélectionner une option de menu pour changer les calculatrices (ie: basique et scientifique). En ce moment je suis en train de tester si voici mon code correspondant à cette question jusqu'à présent (j'utilise scène 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 essayé pas mal de choses déjà. Peu importe quoi, je reçois toujours cette NullPointerException. Je sens qu'il peut avoir à voir avec la mise en quelque chose dans le constructeur de la scène, mais je 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é à l'aide des 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(); 
    } 

} 
+0

J'ai joué à l'aide des suggestions ci-dessous et ai eu à travailler – Megan

Répondre

2

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

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)); 
    } 
} 

Je peux donc é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"); 

C'était une solution de contournement pour une application plein écran, où la transition a été montré MacOS plein écran à chaque fois une étape passe sa scène.

2

au lieu de passer Scenes, mettez un nœud racine déjà existant Scene

+1

je l'ai essayé, mais je continue à obtenir une exception de pointeur NULL. Après avoir reçu deux commentaires à propos de la même chose, j'ai décidé de poster mon message d'exception, voir ci-dessus. – Megan

+0

Dans votre code, vous mélangez les concepts de contrôleur 'Application' et FXML. Chacun a un cycle de vie d'initialisation différent. Les contrôleurs FXML sont basés sur le principe de l'injection de dépendances et l'initialisation doit être faite dans la méthode 'init'. Lire sur les contrôleurs FXML. Vous pouvez également voir ce qui suit http://stackoverflow.com/questions/34785417/javafx-fxml-controller-constructor-vs-initialize-method –

+0

Alors, comment puis-je changer de scène. J'ai essayé d'utiliser la méthode init et de définir un paramètre de chaîne. Si je passais dans une chaîne telle que "test" et que j'utilisais un syso pour imprimer le résultat, cela imprimerait le test. Mais si je passais une chaîne avec le fichier FXML et que j'essayais de définir une scène, cela me donnerait une exception de pointeur nul – Megan

0

Si vous voulez aller de pair avec l'évolution de la scène que vous le feriez comme ceci (notez que la scène est un 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 une meilleure solution pour il suffit de changer le contenu racine de la scène existante:

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

    primaryStage.getScene().setRoot(pane); 
} 
+0

J'ai essayé ceci mais je reçois toujours une exception de pointeur nul. Après avoir reçu deux commentaires à propos de la même chose, j'ai décidé de poster mon message d'exception, voir ci-dessus. – Megan

+0

Quel est le code sur la ligne où vous obtenez le 'NullPointerException'? – hotzst

+0

Ci-dessus j'ai ajouté l'exception que j'ai reçue et il y a des notes en bas. Mais j'ai fatigué un couple d'exemples similaires sans utiliser Scene Builder et ça a fonctionné parfaitement bien donc c'est sûrement quelque chose avec Scene Builder – Megan

0

Il semble OP déjà résolu mais comme il est encore ouvert et non résolu je vais partager une solution que j'ai trouvé dans une autre réponse. N'oubliez pas de sélectionner une réponse correcte ou de poster votre propre solution lorsqu'une question est résolue, cela aide les personnes qui s'exécutent dans le même problème dans le futur (comme je l'ai fait).

Je viens de courir dans le même numéro et this answer a 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 .: N'oubliez pas de vérifier la réponse originale et de la revu à la hausse. Le gars mérite ...

PPS .: Je ne suis pas sûr de simplement copier une réponse est correcte (au lieu de partager simplement le lien par un commentaire) mais puisque cela n'a pas encore une réponse correcte, j'ai décidé de le faire pour la visibilité .

0
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

Certaines explications seraient cool avec un tel exemple de code long. – ChristianM

-1
<?xml version="1.0" encoding="UTF-8"?> 
<?import javafx.scene.image.*?> 
<?import javafx.scene.text.*?> 
<?import java.lang.*?> 
<?import java.util.*?> 
<?import javafx.scene.*?> 
<?import javafx.scene.control.*?> 
<?import javafx.scene.layout.*?> 
<AnchorPane id="AnchorPane" prefHeight="491.0" prefWidth="386.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="todoapp.TypesController"> 
<children> 
    <CheckBox fx:id="c1" layoutX="55.0" layoutY="125.0" mnemonicParsing="false" onAction="#clicked" text="ADD dcu" /> 
    <CheckBox fx:id="c2" layoutX="55.0" layoutY="177.0" mnemonicParsing="false" onAction="#clicked1" text="Display dcu" /> 
    <Label layoutX="31.0" layoutY="58.0" prefHeight="37.0" prefWidth="276.0" text="Choose any one of the options" textFill="#1b29cd"> 
    <font> 
     <Font name="Arial Bold" size="18.0" /> 
    </font> 
    </Label> 
</children> 

+0

s'il vous plaît modifier votre première réponse et ajouter les extraits des autres réponses (plus expliquer comment/pourquoi ils résolvent le problème comme suggéré dans le commentaire) – kleopatra

+0

Juste pour que vous sachiez que j'ai posté cela comme il ya 2 ans. Je pense que tout ce que j'ai fait était de prendre des suggestions à partir des réponses, a fait plus de recherche sur google, puis a trouvé la réponse. J'étais encore très novice en programmation et je n'avais aucune idée de ce que je faisais – Megan