2016-05-13 2 views
2

Я просмотрел много страниц, чтобы попытаться выяснить, как сменить сцены, но я не увенчался успехом.Как переключать сцены в JavaFX

У меня есть калькулятор, и моя цель - выбрать пункт меню для изменения Калькулятор (т. Е. Базовый и научный). Сейчас я просто тестирование так вот мой код отношение к этому вопросу до сих пор (я использую 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 Я пробовал довольно много вещей уже. Независимо от того, я всегда получаю это исключение NullPointerException. У меня есть чувство, что это, возможно, придется делать с установкой что-то в сцене строитель, но я просто не смог найти ответ

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

РАБОЧИЙ КОД:

Я играл вокруг с помощью предложения ниже и использовать этот код чтобы сделать его работу:

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

Я играл, используя предложения ниже, и получил его на работу – Megan

ответ

2

Я написал этот контроллер, чтобы отслеживать различные сценарии.

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

Так что я могу написать:

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

Это обходной путь для полноэкранного приложения, где полноэкранный режим перехода MacOS было показано, каждый раз, когда сцена переключает свою сцену.

2

Вместо переключения Scenes, включите корневой узел на уже существующих Scene

+1

Я попробовал это, но я получаю исключения нулевого указателя. Получив два комментария о том же, я решил опубликовать мое сообщение об исключениях, см. Выше. – Megan

+0

В вашем коде вы смешиваете понятия «приложение» и FXML. Каждый из них имеет различный жизненный цикл инициализации. FXML-контроллеры основаны на принципе ввода зависимостей, и инициализация должна выполняться в методе 'init'. Читайте на контроллерах FXML. Вы также можете увидеть следующее http://stackoverflow.com/questions/34785417/javafx-fxml-controller-constructor-vs-initialize-method –

+0

Итак, как бы я переключил сцену. Я попытался использовать метод init и установил строковый параметр. Если я передал строку, например «test», и использовал syso для распечатки результата, он распечатал тест. Но если я передал строку с файлом FXML и попытался установить сцену, это дало бы мне исключение нулевого указателя – Megan

0

Если вы хотите, чтобы идти вместе с изменением сцены вы могли бы сделать это следующим образом (обратите внимание, что этап является членом приложения):

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

Однако, как уже указывалось на @Eugene_Ryzhikov это лучшее решение чтобы просто изменить корневой контент существующей сцены:

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

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

Я пробовал это, но я продолжаю получать исключение из null-указателя. Получив два комментария о том же, я решил опубликовать мое сообщение об исключениях, см. Выше. – Megan

+0

Что такое код в строке, где вы получаете 'NullPointerException'? – hotzst

+0

Выше я добавил исключение, которое я получил, и внизу есть заметки. Но я устал от пары подобных примеров без использования Scene Builder, и он работал отлично, так что это точно, что-то с Scene Builder – Megan

0

Кажется, что ОП уже решил это, но поскольку он все еще открыт и нераскрыт, я поделюсь решением, которое я нашел в другом ответе. Не забудьте выбрать правильный ответ или отправить собственное решение, когда вопрос будет решен, это поможет людям в будущем работать в одной и той же проблеме (например, я сделал).

Я только что запустил эту же проблему, и this answer решил мою проблему отлично, будучи коротким и чистым.

@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 .: Не забудьте проверить исходный ответ и перенести его. Парень заслуживает ...

PPS .: Я не уверен, что просто копирование ответа в порядке (вместо того, чтобы просто поделиться ссылкой с комментарием), но поскольку у этого нет правильного ответа, но я решил сделать это для видимости ,

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

Некоторое объяснение было бы круто с таким длинным примером кода. – 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

, пожалуйста, отредактируйте ваш первый ответ и добавьте фрагменты из других ответов (а также объясните, почему/почему они решают проблему, как это предложено в комментарии). – kleopatra

+0

Просто, чтобы вы знали, что я опубликовал это, как 2 года назад. Я думаю, что все, что я сделал, это принимать предложения из ответов, делать еще несколько поисков в Google, а затем придумал ответ. Я все еще был новичком в программировании и понятия не имел, что я делаю – Megan

Смежные вопросы