it-swarm.com.ru

Как переключать сцены в 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();
    }

}
4
Megan

Я написал этот контроллер для отслеживания различных сценографов.

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 показывался каждый раз, когда сцена переключает свою сцену.

6
MrEbbinghaus

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

3
Eugene Ryzhikov

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

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

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

Я просто столкнулся с той же проблемой и этот ответ решил свою проблему отлично, будучи коротким и чистым.

@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
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