使用自己的FXML动态加载新选项卡



我想写一个应用程序,它有几个选项。用户可以在菜单中选择一个选项,并创建一个选项卡,该选项卡从另一个fxml文件(也有另一个视图控制器)加载其视图。目前我的代码看起来像:

Tab t = new Tab("My New Tab");
try {
t.setClosable(true);
t.setId("test");
t.setContent(FXMLLoader.
load(getClass().
getResource("/package/NewTabView.fxml")));
} catch (Exception e) {
}
tabPane.getTabs().add(t);
selectionModel.selectLast();

希望你能帮助我,因为我得到以下例外:

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException

就像@DVarga所说的那样,您需要检查NewTabView.fxml文件的位置。

以下是一个可以帮助您的示例:

  • 这里有两个FXML文件及其控制器类
  • firstViewFXML文件是包含TabPane的文件
  • secondViewFXML文件包含要在第一个TabPane中的新Tab中动态加载的内容
  • MainApp类中没有什么特别之处,我们只是加载firstView并设置其控制器
  • 有趣的事情发生在createTabDynamically()方法中,我们加载secondView的FXML文件并设置其控制器,然后实例化一个新选项卡并将secondView设置为其内容,最后将其添加到TabPane

FirstView.fxml

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<BorderPane fx:id="container" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<top>
<MenuBar BorderPane.alignment="CENTER">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem fx:id="closeMI" mnemonicParsing="false" text="Close" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Action">
<items>
<MenuItem fx:id="openTabMI" mnemonicParsing="false" text="Open the new tab" />
</items>
</Menu>
</menus>
</MenuBar>
</top>
<center>
<TabPane fx:id="tabPane" prefHeight="200.0" prefWidth="200.0" tabClosingPolicy="ALL_TABS">
<tabs>
<Tab fx:id="myTab" closable="false" text="MyTab">
<content>
<VBox>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
<children>
<Label text="Hello From the first view" />
</children>
</VBox>
</content>
</Tab>
</tabs>
</TabPane>
</center>
</BorderPane>

SecondView.FXML

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<VBox fx:id="container" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Label fx:id="secondInfoLbl" text="This is the second view">
<font>
<Font size="14.0" />
</font>
</Label>
</children>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
</VBox>

FirstViewController.java

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.VBox;
public class FirstViewController implements Initializable {
@FXML private MenuItem openTabMI, closeMI;
@FXML private TabPane tabPane;
private Tab myDynamicTab;
@Override
public void initialize(URL location, ResourceBundle resources) {
openTabMI.setOnAction((event)->{
createTabDynamically();
});
closeMI.setOnAction((event)->{Platform.exit();});
}
private void createTabDynamically() {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("secondView.fxml"));
loader.setController(new SecondViewController());
try {
Parent parent = loader.load();
myDynamicTab = new Tab("A Dynamic Tab");
myDynamicTab.setClosable(true);
myDynamicTab.setContent(parent);
tabPane.getTabs().add(myDynamicTab);
} catch (IOException e) {
e.printStackTrace();
}
}
}

SecondViewController.java

import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
public class SecondViewController implements Initializable {
@FXML private Label secondInfoLbl;
@Override
public void initialize(URL url, ResourceBundle rb) {
secondInfoLbl.setText("Hello from the second view");
}
}

MainApp.java

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class MainApp extends Application {
public static void main(String [] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("FirstView.fxml"));
FirstViewController firstViewController = new FirstViewController();
loader.setController(firstViewController);
Parent parent = loader.load();
Scene scene = new Scene(parent);
primaryStage.setScene(scene);
primaryStage.show();
}
}

相关内容

最新更新