как поменять местами экраны в javafx-приложении в классе контроллера?

<p>эй, я долго искал в сети, но не смог найти решение следующей проблемы:</p><p>в javafx вы получили 3 основных файла; класс контроллера, файл fxml и класс приложения. теперь я хочу отреагировать в контроллере на нажатие кнопки (которое прекрасно работает) и изменить экран на этом щелчке (что вы обычно делаете с stage.setscreen ()), но я не имею никакого отношения к этапу (который вы можно найти в классе приложений).</p><p>применение-sample:</p><pre><code>public class javafxapplication4 extends application { @override public void start(stage stage) throws exception { parent root = fxmlloader.load(getclass().getresource("sample.fxml")); scene scene = new scene(root); stage.setscene(scene); stage.show(); } /** * the main() method is ignored in correctly deployed javafx application. * main() serves only as fallback in case the application can not be * launched through deployment artifacts, e.g., in ides with limited fx * support. netbeans ignores main(). * * @param args the command line arguments */ public static void main(string[] args) { launch(args); } } </code></pre><p>fxml-sample:</p><pre><code><?xml version="1.0" encoding="utf-8"?> <?import java.lang.*?> <?import java.util.*?> <?import javafx.scene.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <anchorpane id="anchorpane" prefheight="200.0" prefwidth="320.0" xmlns:fx="http://javafx.com/fxml" fx:controller="javafxapplication4.samplecontroller"> <children> <button id="button" fx:id="nextscreen" layoutx="126.0" layouty="90.0" onaction="#handlebuttonaction" text="next screen" /> <label fx:id="label" layoutx="126.0" layouty="120.0" minheight="16.0" minwidth="69.0" /> </children> </anchorpane> </code></pre><p>контроллер-sample:</p><pre><code>public class samplecontroller implements initializable { @fxml private label label; @fxml private void handlebuttonaction(actionevent event) { system.out.println("you clicked me!"); label.settext("hello world!"); //here i want to swap the screen! } @override public void initialize(url url, resourcebundle rb) { // todo } } </code></pre><p>я был бы благодарен за любую помощь.</p>

<pre><code>@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())); } </code></pre>

<p>я нашел этот старый вопрос, входя в java и пытаясь решить одну и ту же проблему ........ поскольку я хотел, чтобы сцены запоминали содержимое между коммутаторами, я не мог использовать принятый ответ, потому что при переключении между сценами он создает экземпляры. их снова (теряя свое предыдущее состояние).</p><p>в любом случае принятый ответ и <a href="https://stackoverflow.com/a/17227496/519035">ответ на аналогичный вопрос</a> дал мне подсказку о том, как переключать сцены, не теряя их состояния .. основная идея состоит в том, чтобы внедрить экземпляр сцены в другой контроллер, чтобы контроллеру не нужно создавать новую сцену снова и снова, но он может использовать уже существующий экземпляр (с его состоянием).</p><p>итак, вот основной класс, который создает сцены:</p><pre><code>public class main extends application { public static void main(string[] args) { launch(args); } @override public void start(stage primarystage) throws exception { // getting loader and a pane for the first scene. // loader will then give a possibility to get related controller fxmlloader firstpaneloader = new fxmlloader(getclass().getresource("firstlayout.fxml")); parent firstpane = firstpaneloader.load(); scene firstscene = new scene(firstpane, 300, 275); // getting loader and a pane for the second scene fxmlloader secondpageloader = new fxmlloader(getclass().getresource("secondlayout.fxml")); parent secondpane = secondpageloader.load(); scene secondscene = new scene(secondpane, 300, 275); // injecting second scene into the controller of the first scene firstcontroller firstpanecontroller = (firstcontroller) firstpaneloader.getcontroller(); firstpanecontroller.setsecondscene(secondscene); // injecting first scene into the controller of the second scene secondcontroller secondpanecontroller = (secondcontroller) secondpageloader.getcontroller(); secondpanecontroller.setfirstscene(firstscene); primarystage.settitle("switching scenes"); primarystage.setscene(firstscene); primarystage.show(); } } </code></pre><p>и вот оба контроллера:</p><pre><code>public class firstcontroller { private scene secondscene; public void setsecondscene(scene scene) { secondscene = scene; } public void opensecondscene(actionevent actionevent) { stage primarystage = (stage)((node)actionevent.getsource()).getscene().getwindow(); primarystage.setscene(secondscene); } } </code></pre><p>да, второй выглядит так же (некоторая логика, вероятно, может быть разделена, но текущее состояние достаточно в качестве доказательства концепции)</p><pre><code>public class secondcontroller { private scene firstscene; public void setfirstscene(scene scene) { firstscene = scene; } public void openfirstscene(actionevent actionevent) { stage primarystage = (stage)((node)actionevent.getsource()).getscene().getwindow(); primarystage.setscene(firstscene); } } </code></pre>

<p>вы тоже можете попробовать это.</p><pre><code>public void onbtnclick(actionevent event) { try { fxmlloader loader = new fxmlloader(getclass().getresource("login.fxml")); stage stage = (stage) btn.getscene().getwindow(); scene scene = new scene(loader.load()); stage.setscene(scene); }catch (ioexception io){ io.printstacktrace(); } } </code></pre>