我有一个调用 super 构造函数的类。父类(super class)加载一个 FXML 包装器布局,然后加载另一个 FXML 布局作为包装器内元素的子元素,如下所示:
// Reference 'outer' FXML
URL outer_url = getClass().getResource("/main/resources/fxml/RootNode.fxml");
FXMLLoader outer_loader = new FXMLLoader(outer_url);
outer_loader.setRoot(this);
outer_loader.setController(this);
// Reference 'inner' FXML
URL inner_url = getClass().getResource(fxml_path);
FXMLLoader inner_loader = new FXMLLoader(inner_url);
try {
outer_loader.load();
/* The root of inner_loader is a component of outer_loader FXML,
* thus outer_loader.load() must be called first. */
inner_loader.setRoot(outer_loader.getNamespace().get("vbox_center"));
inner_loader.setController(controller);
inner_loader.load();
} catch (IOException e) {
e.printStackTrace();
}
我需要该类作为inner_loader的 Controller 。这可能吗?我尝试通过 super 构造函数传递对该类的引用,但是在调用 super 构造函数之前我无法引用“this”。
有什么想法吗?提前致谢。
编辑:我还尝试直接通过内部 FXML 文件指定 Controller ,但这导致了问题。
编辑2:我忘了指定,加载两个FXML布局的父类(super class)是由多个节点继承的,这就是为什么我不能只创建 Controller 的实例并将其直接传递给inner_loader。我需要(以某种方式)将实例引用传递给父类(super class)并将其用作 Controller 。
最佳答案
尚不完全清楚您要做什么,但看起来您正在尝试使用继承和 FXML-based custom components创建具有特化的模板。
这是可能的。您可以在构造函数中以通常的方式加载 FXML。由于每个构造函数都会调用其父类(super class)构造函数,因此父类(super class) FXML 将在子类 FXML 之前加载。
项目布局:
模板:
模板.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.layout.VBox?>
<fx:root xmlns:fx="http://javafx.com/fxml/1" type="BorderPane">
<top>
<MenuBar>
<menus>
<Menu text="File">
<items>
<MenuItem text="Quit" onAction="#quit"/>
</items>
</Menu>
</menus>
</MenuBar>
</top>
<center>
<VBox fx:id="vboxCenter"/>
</center>
</fx:root>
组件(Template.java):
package template;
import java.io.IOException;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
public class Template extends BorderPane {
@FXML
private VBox vboxCenter ;
public Template() throws IOException {
FXMLLoader loader = new FXMLLoader(Template.class.getResource("Template.fxml"));
loader.setRoot(this);
loader.setController(this);
loader.load();
}
protected final VBox getCenterContentHolder() {
return vboxCenter ;
}
@FXML
private void quit() {
vboxCenter.getScene().getWindow().hide();
}
}
专业:
Home.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.text.Font?>
<fx:root xmlns:fx="http://javafx.com/fxml/1" type="VBox" alignment="CENTER">
<Label fx:id="welcomeLabel" text="Welcome" />
</fx:root>
组件(Home.java):
package home;
import java.io.IOException;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Label;
import javafx.scene.text.Font;
import template.Template;
public class Home extends Template {
@FXML
private Label welcomeLabel ;
public Home() throws IOException {
// not necessary to explicitly call super(), it is called by default
// this call loads the template defined by the superclass
super();
FXMLLoader loader = new FXMLLoader(Home.class.getResource("Home.fxml"));
loader.setRoot(getCenterContentHolder());
loader.setController(this);
loader.load();
welcomeLabel.setFont(Font.font("Arial", 48));
}
}
应用:
package application;
import java.io.IOException;
import home.Home;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
Scene scene = new Scene(new Home(), 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
关于JavaFx 嵌套 Controller ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41030395/