问题描述:
在JavaFX中实现两个FXML公用同一个控制器,其中第一个FXML包含一个TabPane其中包含一个按钮,第二个FXML只包含一个按钮,我要实现的是第一个FXML中TabPane中的按钮被按下后,在TabPane新建一个Tab,其中加载内容为第二个FXML的内容,第二个FXML中的按钮被按下后,再在第一个FXML中的TabPane放置一个新的Tab,其中新的Tab加载的内容为第二个FXML的内容为第二个Tab。
解决方法
传统写法将会导致空指针异常,可以这样写:
首先,创建一个控制器类(例如 Controller.java),用于处理两个FXML文件中的逻辑。在控制器类中,您需要定义一个 TabPane 和一个方法来处理第一个FXML中的按钮点击事件,用于创建新的 Tab 并加载第二个FXML的内容。
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.AnchorPane;
import java.io.IOException;
public class Controller {
@FXML
private TabPane tabPane;
@FXML
private Button addButton;
@FXML
public void initialize() {
addButton.setOnAction(event -> createNewTab());
}
private void createNewTab() {
try {
Tab tab = new Tab();
FXMLLoader loader = new FXMLLoader(getClass().getResource("second.fxml"));
AnchorPane content = loader.load();
tab.setContent(content);
tabPane.getTabs().add(tab);
} catch (IOException e) {
e.printStackTrace();
}
}
public void handleSecondButton() {
Tab tab = new Tab();
FXMLLoader loader = new FXMLLoader(getClass().getResource("second.fxml"));
try {
AnchorPane content = loader.load();
tab.setContent(content);
tabPane.getTabs().add(tab);
} catch (IOException e) {
e.printStackTrace();
}
}
}
接下来,创建第一个FXML文件(例如 first.fxml)并定义一个包含一个 TabPane 和一个按钮的布局。
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Controller">
<TabPane fx:id="tabPane">
<!-- TabPane内容 -->
</TabPane>
<Button fx:id="addButton" text="新建Tab"/>
</VBox>
然后,创建第二个FXML文件(例如 second.fxml),其中只包含一个按钮。
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Controller">
<Button text="第二个FXML中的按钮" onAction="#handleSecondButton"/>
</VBox>
最后,在主应用程序类(例如 Main.java)中加载第一个FXML文件,并将控制器与其关联。
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("first.fxml"));
Parent root = loader.load();
Controller controller = loader.getController(); // 获取控制器实例
Scene scene = new Scene(root, 400, 300);
primaryStage.setScene(scene);
primaryStage.show();
}
}
现在,当您在第一个FXML的 TabPane 中的按钮被按下时,将创建一个新的 Tab,其中包含第二个FXML的内容。同样,当第二个FXML中的按钮被按下时,将在第一个FXML的 TabPane 中添加一个新的 Tab,其中内容为第二个FXML。