当前位置: 首页 > 知识库问答 >
问题:

如何获得包含的FXML的控制器?

田易安
2023-03-14

我有一个围绕JavaFXML和scenebuilder构建的简单的两个选项卡应用程序。这些选项卡目前什么都不做,因为我在尝试加载它们时无法通过null指针异常。

java和fxml文件安排在一个Netbeans项目中,如下所示:

主应用程序:应用程序主类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:

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语句只是试图获取对两个选项卡的引用,即详细控制器和输入控制器,以执行某些操作。但是,当这些未注释并运行时,将输出以下转储:

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

如上所述,细节和输入控制器为空,但为完整性起见,它们如下所示:

InputView.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>

控制器输入控制器。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) {}  
}

详细iew.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" />

控制器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) {}  
}

共有1个答案

方玄天
2023-03-14

本文描述了获取嵌入式FXML控制器引用的方法。

您只需为包含的资源提供fx: id

   <fx:include fx:id="IncludedView" source="InputView.fxml" />

获取对主控制器中包含视图的引用:

@FXML private Parent IncludedView;

除了嵌入式元素的变量名之外,只需附加单词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);
    }
}

为了未来的读者,一份MRE:

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

主视图。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>

主ontroller.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();
    }
}

包含视图。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>

包括ViewController。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();
    }
}
 类似资料:
  • 我有以下代码: 在fxml文件中有一个对控制器类的引用。如何获取控制器对象? fxml:

  • 我有一个用fxml写的边框窗格,它有左窗格和中央窗格的可互换布局。 边框窗格fxml: fxml文件中的一个按钮将在控制器中运行一些代码,用从另一个fxml文件加载的VBox更改边框窗格的右侧。 现在的问题是,我如何告诉右窗格的fxml使用与主窗格相同的控制器?换句话说,我想继承控制器。 如果我在fxml中用定义控制器,它只会生成一个新实例,如果我不定义它,它只会给出错误,因为它里面的按钮没有可参

  • 我需要你的帮助来解决这个问题,我想从不同的包中包含子fxml。如果child.fxml在同一位置,我可以将它们包含到parent.fxml中,但不知道如何将child.fxml添加到parent.fxml中,当两者都在不同的位置/包中时。 先谢谢你。

  • 问题内容: 当我仅具有对该INPUT的引用时,需要获得对该INPUT的FORM父级的引用。JavaScript有可能吗?如果愿意,请使用jQuery。 这不起作用: 问题答案: 作为输入的本机DOM元素还具有指向它们所属形式的属性: IE 4.0+,Firefox 1.0+,Opera9.0+支持输入字段的属性,这是jQuery保证的更多浏览器,因此您应该坚持这一点。 如果这是另一种类型的元素(不

  • 问题内容: 当我在JavaFX中调用FXMLLoader#load()时会发生什么? 假设FXML控制器扩展了具有构造函数的类。是否可以保证构造函数将被调用?如果没有,将如何创建该对象的新实例?例如,在下面的代码中,是否将调用TextField()构造函数? 我已经尝试过搜索这个,但是除了“从FXML文档中加载对象层次结构”之外,似乎没有关于它的文档。来自http://docs.oracle.co

  • 我已经试着搜索了这篇文章,但是除了“从FXML文档加载对象层次结构”之外,似乎没有关于它的文档。摘自http://docs.oracle.com/javafx/2/api/javafx/fxml/fxmlloader.html 你的回答将不胜感激。多谢!