[英]JavaFX: How to change scene (FXML) from MenuItem
At 76, I am trying to learn Java and have produced a number of accounting related tutorials that successfully change scenes. 76 岁时,我正在尝试学习 Java,并制作了许多成功改变场景的会计相关教程。 Now looking at a structure using menubar and menu items to cope with linking 14 chapters as one of the items on the menubar.
现在查看使用菜单栏和菜单项的结构来处理链接 14 个章节作为菜单栏上的项目之一。
All examples I have seen/watched show a simple println
for each MenuItem
.我见过/看过的所有示例都为每个
MenuItem
显示了一个简单的println
。 I have this working OK, but when I try to copy my FXMLLoader
from my previous applications it doesn't like it.我的这个工作正常,但是当我尝试从我以前的应用程序中复制我的
FXMLLoader
,它不喜欢它。
I get this cannot find symbol: symbol: method getScene() location: variable mbarchapter1 of type MenuItem
我得到这个找不到符号:
symbol: method getScene() location: variable mbarchapter1 of type MenuItem
My code is:我的代码是:
package accountingsnapshots;
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.Parent;
import javafx.scene.Scene;
import javafx.scene.control.MenuItem;
import javafx.stage.Stage;
public class AccountingSnapshotsController implements Initializable {
@FXML
private MenuItem mbarhome;
@FXML
private MenuItem mbarchapter1;
@FXML
private MenuItem mbarchapter2;
@FXML
private MenuItem mbarchapter3;
@FXML
private MenuItem mbarchapter4;
@FXML
private MenuItem mbarcalculator;
@FXML
private MenuItem mbarglossary;
@FXML
private MenuItem mbarhelp;
Stage stage;
@FXML Parent root;
@FXML
private void handleButtonAction(ActionEvent e) throws IOException {
if(e.getSource()==mbarhome){
System.out.println("this is Home");
}
else if(e.getSource()==mbarchapter1){
System.out.println("this is chap 1");
//get reference to the button's stage
stage = (Stage) root.getScene().getWindow();
//load up OTHER FXML document
root = FXMLLoader.load(getClass().getResource("AccountingSnapshots_1.fxml"));
//create a new scene with root and set the stage
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
else if(e.getSource()==mbarchapter2){
System.out.println("this is chap 2");
}
else if(e.getSource()==mbarchapter3){
System.out.println("this is chap 3");
}
else if(e.getSource()==mbarchapter4){
System.out.println("this is chap 4");
}
else if(e.getSource()==mbarcalculator){
System.out.println("this is Calculator");
}
else if(e.getSource()==mbarglossary){
System.out.println("this is Glossary");
}
else if(e.getSource()==mbarhelp){
System.out.println("this is Help");
}
}
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
My FXML file has fx:ids against the menuItems.我的 FXML 文件对菜单项有 fx:ids。 Shown below:
如下图:
<?xml version="1.0" encoding="UTF-8"?>
<?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="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="accountingsnapshots.AccountingSnapshotsController">
<children>
<MenuBar layoutY="-1.0" prefHeight="30.0" prefWidth="858.0">
<menus>
<Menu fx:id="mbarhome" mnemonicParsing="false" onAction="#handleButtonAction" text="Home">
<items>
<MenuItem mnemonicParsing="false" text="Home" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Chapters">
<items>
<MenuItem fx:id="mbarchapter1" mnemonicParsing="false" onAction="#handleButtonAction" text="Ch.1 - Introduction to final accounts" />
<MenuItem fx:id="mbarchapter2" mnemonicParsing="false" onAction="#handleButtonAction" text="Ch.2 - Double entry bookkeeping" />
<MenuItem fx:id="mbarchapter3" mnemonicParsing="false" onAction="#handleButtonAction" text="Ch.3 - Accounting adjustments" />
<MenuItem fx:id="mbarchapter4" mnemonicParsing="false" onAction="#handleButtonAction" text="Ch.4 - Introduction to final accounts" />
</items>
</Menu>
<Menu fx:id="mbarcalculator" mnemonicParsing="false" onAction="#handleButtonAction" text="Calculator">
<items>
<MenuItem mnemonicParsing="false" text="Calculator" />
</items>
</Menu>
<Menu fx:id="mbarglossary" mnemonicParsing="false" onAction="#handleButtonAction" text="Glossary">
<items>
<MenuItem mnemonicParsing="false" text="Glossary" />
</items>
</Menu>
<Menu fx:id="mbarhelp" mnemonicParsing="false" onAction="#handleButtonAction" text="Help">
<items>
<MenuItem mnemonicParsing="false" text="Help" />
</items>
</Menu>
</menus>
</MenuBar>
</children>
</AnchorPane>
This is the output when running the application:这是运行应用程序时的输出:
Created dir: C:\Users\john\Documents\NetBeansProjects\AccountingSnapshots\build\empty
Created dir: C:\Users\john\Documents\NetBeansProjects\AccountingSnapshots\build\generated-sources\ap-source-output
Compiling 2 source files to C:\Users\john\Documents\NetBeansProjects\AccountingSnapshots\build\classes
Copying 5 files to C:\Users\john\Documents\NetBeansProjects\AccountingSnapshots\build\classes
compile:
Created dir: C:\Users\john\Documents\NetBeansProjects\AccountingSnapshots\dist
Detected JavaFX Ant API version 1.3
Launching <fx:jar> task from C:\Program Files\Java\jdk1.8.0_31\jre\..\lib\ant-javafx.jar
Warning: From JDK7u25 the Codebase manifest attribute should be used to restrict JAR repurposing.
Please set manifest.custom.codebase property to override the current default non-secure value '*'.
Launching <fx:deploy> task from C:\Program Files\Java\jdk1.8.0_31\jre\..\lib\ant-javafx.jar
jfx-deployment-script:
jfx-deployment:
jar:
Copying 12 files to C:\Users\john\Documents\NetBeansProjects\AccountingSnapshots\dist\run53408212
jfx-project-run:
Executing C:\Users\john\Documents\NetBeansProjects\AccountingSnapshots\dist\run53408212\AccountingSnapshots.jar using platform C:\Program Files\Java\jdk1.8.0_31\jre/bin/java
this is chap 1
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1762)
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1645)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.control.MenuItem.fire(MenuItem.java:462)
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.doSelect(ContextMenuContent.java:1364)
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.lambda$createChildren$324(ContextMenuContent.java:1317)
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer$$Lambda$147/1926554713.handle(Unknown Source)
at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3724)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3452)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1728)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2461)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:348)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:273)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:382)
at com.sun.glass.ui.View.handleMouseEvent(View.java:553)
at com.sun.glass.ui.View.notifyMouse(View.java:925)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$141(WinApplication.java:102)
at com.sun.glass.ui.win.WinApplication$$Lambda$37/96639997.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1757)
... 43 more
Caused by: javafx.fxml.LoadException:
file:/C:/Users/john/Documents/NetBeansProjects/AccountingSnapshots/dist/run53408212/AccountingSnapshots.jar!/accountingsnapshots/AccountingSnapshots_1.fxml:16
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2595)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2573)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2435)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3208)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3169)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3142)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3118)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3098)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3091)
at accountingsnapshots.AccountingSnapshotsController.handleButtonAction(AccountingSnapshotsController.java:53)
... 53 more
Caused by: java.lang.IllegalArgumentException: Unable to coerce MenuButton@35398aab[styleClass=menu-button]'Home' to class javafx.scene.control.MenuItem.
at com.sun.javafx.fxml.BeanAdapter.coerce(BeanAdapter.java:495)
at javafx.fxml.FXMLLoader$PropertyElement.add(FXMLLoader.java:1387)
at javafx.fxml.FXMLLoader$ValueElement.processEndElement(FXMLLoader.java:784)
at javafx.fxml.FXMLLoader.processEndElement(FXMLLoader.java:2817)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2526)
... 61 more
Corrected the second .fxml file, changing MenuButton to MenuItem.更正了第二个 .fxml 文件,将 MenuButton 更改为 MenuItem。 This is the result in the output section:
这是输出部分的结果:
ant -f C:\\Users\\john\\Documents\\NetBeansProjects\\AccountingSnapshots jfxsa-run
init:
Deleting: C:\Users\john\Documents\NetBeansProjects\AccountingSnapshots\build\built-jar.properties
deps-jar:
Updating property file: C:\Users\john\Documents\NetBeansProjects\AccountingSnapshots\build\built-jar.properties
compile:
Detected JavaFX Ant API version 1.3
jfx-deployment:
jar:
Copying 12 files to C:\Users\john\Documents\NetBeansProjects\AccountingSnapshots\dist\run581163156
jfx-project-run:
Executing C:\Users\john\Documents\NetBeansProjects\AccountingSnapshots\dist\run581163156\AccountingSnapshots.jar using platform C:\Program Files\Java\jdk1.8.0_31\jre/bin/java
this is chap 1
Deleting directory C:\Users\john\Documents\NetBeansProjects\AccountingSnapshots\dist\run581163156
jfxsa-run:
BUILD SUCCESSFUL (total time: 19 seconds)
Any help appreciated任何帮助表示赞赏
MenuItem
is not a subclass of Node
, so it doesn't inherit a getScene()
method . MenuItem
不是Node
的子类,因此它不继承getScene()
方法。
The simplest solution is just to call getScene()
on any scene graph node which you know to be in the same scene as the menubar containing your menu item.最简单的解决方案是在您知道与包含菜单项的菜单栏位于同一场景中的任何场景图节点上调用
getScene()
。
stage = (Stage) someNode.getScene().getWindow();
where someNode
is any Node
that you have injected into your controller with @FXML
.其中
someNode
是您使用@FXML
注入控制器的任何Node
。
As you currently only have MenuItem
s injected into your controller, you need to inject some node for this purpose.由于您目前只有
MenuItem
s 注入到您的控制器中,因此您需要为此目的注入一些节点。 The most natural one would be the root of the FXML.最自然的一个是 FXML 的根。 To do this, add a
fx:id="root"
attribute to your FXML's root element, and then just change the declaration of the root
field in the controller so that it is injected:为此,将
fx:id="root"
属性添加到 FXML 的根元素,然后只需更改控制器中root
字段的声明,以便注入:
@FXML
private Parent root ;
Then然后
stage = (Stage) root.getScene().getWindow();
should give you the current Stage
, as needed.应该根据需要为您提供当前
Stage
。
This is an old thread, but the answer given was spot on这是一个旧线程,但给出的答案是正确的
Here's a bit of code for anyone that's facing the same issues这是任何面临相同问题的人的一些代码
Normally, I would just pass in a node to the stage object, but as has already been stated - a menu/menuItem cannot be converted to a node.通常,我只会将节点传递给舞台对象,但正如已经说明的那样 - 菜单/菜单项不能转换为节点。 Using the fx:id of the outermost node solves the problem.
使用最外层节点的 fx:id 可以解决问题。 reportAnchorpane is the name of the (root) node for this respective FXML
reportAnchorpane 是此相应 FXML 的(根)节点的名称
public void gotoReports(ActionEvent e) throws IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/Reports/Reports.fxml"));
Parent ReportManager = loader.load();
Scene ReportManagerScene = new Scene(ReportManager);
Stage window = (Stage)reportAnchorPane.getScene().getWindow();
window.setScene(ReportManagerScene);
window.show();
}
On the FXML关于 FXML
<AnchorPane fx:id="reportAnchorPane" prefHeight="500.0" prefWidth="800.0" styleClass="mainFxmlClass" fx:controller="Reports.ReportsController">
<stylesheets>
<URL value="@reports.css" />
</stylesheets>
<children>
<HBox fx:id="Menu" prefHeight="25.0" prefWidth="925.0">
<children>
<MenuBar fx:id="MenuBar" prefHeight="25.0" prefWidth="925.0">
<menus>
<Menu mnemonicParsing="false" text="Window" >
<items>
<MenuItem fx:id="miGotoReportsPage" mnemonicParsing="false" text="Reports" onAction="#gotoReports"/>
</items>
</Menu>
</menus>
</MenuBar>
</children>
</HBox>
</children>
</AnchorPane>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.