我有一个围绕 JavaFXML 和 scenebuilder 构建的简单的两个选项卡应用程序。这些选项卡目前什么都不做,因为我在尝试加载它们时无法通过空指针异常。
java 和 fxml 文件在 Netbeans 项目中的排列如下:
Main Application:应用主类MainApp.java布景,声明如下:
package tabpane;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class MainApp extends Application {
private static Stage primaryStage;
private AnchorPane rootLayout;
public MainApp() {}
@Override
public void start(Stage primaryStage) {
primaryStage.initStyle(StageStyle.UNDECORATED);
MainApp.primaryStage = primaryStage;
MainApp.primaryStage.setTitle("Account Names");
initRootLayout();
}
public void initRootLayout() {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("view/MainView.fxml"));
rootLayout = (AnchorPane) loader.load();
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
Logger.getLogger(MainApp.class.getName()).log(Level.SEVERE, null, e);
System.out.println("MainApp: IOException in method: initRootLayout" + e.getMessage());
System.exit(0);
}
}
public Stage getPrimaryStage() {
return primaryStage;
}
public static void main(String[] args) {
launch(args);
}
}
MainController 类为应用程序声明两个选项卡,输入选项卡和帐户选项卡,以及用于关闭程序的退出按钮。这是主视图。 fxml文件:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="tabpane1.view.MainController">
<children>
<TabPane fx:id="tabPane" prefHeight="345.0" prefWidth="600.0" style="-fx-background-color: blue;" tabClosingPolicy="UNAVAILABLE">
<tabs>
<Tab fx:id="inputTab" closable="false" text="Input">
<content>
<fx:include source="InputView.fxml" />
</content>
</Tab>
<Tab fx:id="detailTab" closable="false" text="Detail">
<content>
<fx:include source="DetailView.fxml" />
</content>
</Tab>
</tabs>
</TabPane>
<Button fx:id="exitBtn" layoutX="529.0" layoutY="355.0" mnemonicParsing="false" onAction="#handleExitBtn" text="Exit" />
</children>
</AnchorPane>
这是 MainController.java 中包含的主视图的 java Controller 类:
package tabpane1.view;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
public class MainController implements Initializable {
@FXML public TabPane tabPane;
@FXML public Tab inputTab;
@FXML public Tab accountTab;
@FXML private Button exitBtn;
public DetailController detailController;
public InputController inputController;
@Override
public void initialize(URL location, ResourceBundle resources) {
detailController = new FXMLLoader(getClass().getResource("DetailView.fxml")).getController();
// System.out.println(detailController.getClass());
inputController = new FXMLLoader(getClass().getResource("InputView.fxml")).getController();
// System.out.println(inputController.getClass());
}
@FXML private void handleExitBtn() {
System.exit(0);
}
}
这两个 println 语句只是试图获取对两个选项卡(即 detailController 和 inputController)的引用以执行某些操作。然而,当这些被取消注释并运行时,输出以下转储:
MainApp: IOException in method: initRootLayout
SEVERE: null
file:/G:/J2EE/TabPane_1/dist/run1314937364/TabPane_1.jar!/tabpane1/view/MainView.fxml
javafx.fxml.LoadException:
file:/G:/J2EE/TabPane_1/dist/run1314937364/TabPane_1.jar!/tabpane1/view/MainView.fxml
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2601)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2579)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2409)
at tabpane1.MainApp.initRootLayout(MainApp.java:43)
at tabpane1.MainApp.start(MainApp.java:33)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$161(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$174(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$172(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$173(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NullPointerException
at tabpane1.view.MainController.initialize(MainController.java:24)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548)
... 13 more
当 printlns 被注释掉时,结果如预期的那样,即正确显示选项卡 Pane :
如前所述,细节和输入 Controller 是空的,但为了完整起见,它们如下所示:
输入 View .fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="tabpane1.view.InputController">
</AnchorPane>
Controller InputController.java:
package tabpane1.view;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.Initializable;
public class InputController implements Initializable {
@Override
public void initialize(URL location, ResourceBundle resources) {}
}
详细 View .fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" style="-fx-background-color: transparent;" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="tabpane1.view.DetailController" />
Controller DetailController.java:
package tabpane1.view;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.Initializable;
public class InputController implements Initializable {
@Override
public void initialize(URL location, ResourceBundle resources) {}
}
最佳答案
在this article 中描述了获取对嵌入式FXML
Controller 的引用的方法。 .
您只需为包含的资源提供一个fx:id
:
<fx:include fx:id="IncludedView" source="InputView.fxml" />
在 MainController
中获取对 IncludedView
的引用:
@FXML private Parent IncludedView;
除了嵌入元素的变量名之外,只需附加单词 Controller 即可获取对其 Controller 的引用:
@FXML private InputController IncludedViewController;
就是这样。
测试它:
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
public class MainController implements Initializable {
@FXML private Parent IncludedView;
@FXML private InputController IncludedViewController; // $IncludedView;+Controller
@Override
public void initialize(URL location, ResourceBundle resources) {
System.out.println(IncludedView.getClass());
System.out.println(IncludedViewController.getClass() );
}
@FXML private void handleExitBtn() {
System.exit(0);
}
}
An MRE for the sake of future readers:
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class GetEmbeddedController extends Application {
@Override
public void start(Stage primaryStage) {
try {
Pane root = (Pane) FXMLLoader.load(getClass().getResource("MainView.fxml"));
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(null);
}
}
MainView.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/10.0.1"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="MainController">
<children>
<fx:include fx:id="includedView" source="IncludedView.fxml" />
<Button layoutX="401.0" layoutY="354.0" onAction="#handleTestBtn" text="Test Included Controller" />
</children>
</AnchorPane>
主 Controller .java
import javafx.fxml.FXML;
import javafx.scene.Parent;
public class MainController{
@FXML private Parent includedView; //not used in this demo
/*
* Get a reference to IncludedView controller simply by appending
* the word Controller in addition to the variable name of the embedded
* element:$IncludedView;+Controller
*/
@FXML private IncludedViewController includedViewController;
@FXML private void handleTestBtn() {
includedViewController.showAlert();
}
}
IncludedView.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Text?>
<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/10.0.1"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="IncludedViewController">
<children>
<Text layoutX="277.0" layoutY="196.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Included Fxml" />
</children>
</AnchorPane>
IncludedViewController.java
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
public class IncludedViewController{
void showAlert(){
Alert alert = new Alert(AlertType.INFORMATION);
alert.setContentText("Alert invoked by IncludedViewController ");
alert.show();
}
}
关于java - 如何获取包含的 FXML 的 Controller ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59551896/