JavaFX可重用FXML代码段 [英] JavaFX Reusable FXML Snippets

查看:141
本文介绍了JavaFX可重用FXML代码段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实现一个选项卡式部分,其中每个选项卡都包含一个表视图。在此表视图中,无论选择哪个选项卡,都会有一个列的子集,但某些选项卡将包含其他列(以编程方式处理)。

I am implementing a tabbed section where each tab will contain a table view. Within this table view, there is a subset of columns that will be rendered regardless of which tab is selected but some tabs will include additional columns (handled programmatically).

由于这些原因,每个标签需要有一个单独的控制器,但我想知道是否可以在每个标签中重复使用标签FXML的内部内容必须复制并粘贴代码。我正在思考一个可重用的组件,我可以在另一个FXML文件中定义它,并且只包含在选项卡部分中。

For these reasons, each tab needs to have a separate controller but I was wondering if it was possible for me to reuse the inner contents of the tab FXML in each tab without having to copy and paste the code. I am thinking along the lines of a reusable component that I could define in another FXML file and just include in the tab section.

具体来说,我想将下面代码中的内容部分放在一个文件中,并在每个文件中引用它,这样我就不必进行更改如果我想在将来改变某些内容,请访问多个文件。我认为这可以通过编程方式实现,但如果可能的话我更喜欢FXML解决方案。

Specifically, I'd like to have the content section in the code below in a single file and just reference it in each file so I don't have to make changes to multiple files if I want to change something in the future. I think this can possibly be achieved programmatically, but I would prefer an FXML solution if possible.

<Tab xmlns:fx="http://javafx.com/fxml/1"
     xmlns="http://javafx.com/javafx/8"
     fx:controller="com.SpecificController"
     id="specificTab" text="Specific Tab Name">

    <content>
        <JFXTreeTableView fx:id="commonTableView" VBox.vgrow="ALWAYS">
            <columns>
                <JFXTreeTableColumn fx:id="nameColumn" text="Name"/>
                <JFXTreeTableColumn fx:id="positionColumn" text="Position"/>
                <JFXTreeTableColumn fx:id="teamColumn" text="Team"/>
                <JFXTreeTableColumn fx:id="selectColumn" text="Select"/>
            </columns>
        </JFXTreeTableView>
    </content>
</Tab>


推荐答案

我绝不是JavaFX专家,但我能够提出这个解决方案。

I am by no means a JavaFX expert, but I was able to come up with this solution.

这是一个MCVE,所以你可以完全重新创建这个示例应用程序并运行它以查看它的实际效果。

This is an MCVE, so you can recreate this sample application completely and run it to see it in action.

此示例对可重用的FXML节点使用 AnchorPane ,但您可以修改它以使用选项卡而不是。我发现重用内容本身有点简单。

This sample uses an AnchorPane for the reusable FXML node, but you could modify it to use a Tab instead. I find reusing the content itself to be a bit simpler, though.

我使用简单的接口来定义我们的标签控件;这允许我们编写一个方法来为每个 Tab 设置内容和单个控制器。

I am using a simple Interface to define our tab controllers; this allows us to write one method that sets the content and the individual controller for each Tab.

Main.java:

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class Main extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {

        try {
            // Load the main layout
            FXMLLoader loader = new FXMLLoader(getClass().getResource("MainLayout.fxml"));

            // Show the Stage
            primaryStage.setWidth(700);
            primaryStage.setHeight(500);
            primaryStage.setScene(new Scene(loader.load()));
            primaryStage.show();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}




FXML文件:

MainLayout.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/9.0.1"
            xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.reusableTabs.MainController">
    <VBox alignment="TOP_CENTER" prefHeight="400.0" prefWidth="600.0" spacing="10.0" AnchorPane.bottomAnchor="0.0"
          AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
        <padding>
            <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
        </padding>
        <Label style="-fx-font-size: 150%; -fx-font-weight: bold;" text="Reusable Tab Content Sample"/>
        <Separator prefWidth="200.0"/>
        <TabPane fx:id="tabPane" prefHeight="200.0" prefWidth="200.0" tabClosingPolicy="UNAVAILABLE"
                 VBox.vgrow="ALWAYS">
            <Tab fx:id="tab1" text="Tab #1"/>
            <Tab fx:id="tab2" text="Tab #2"/>
            <Tab fx:id="tab3" text="Tab #3"/>
        </TabPane>
    </VBox>
</AnchorPane>

TabContent.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0"
            prefWidth="600.0" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1">
    <VBox alignment="CENTER" prefHeight="400.0" prefWidth="600.0" spacing="20.0" AnchorPane.bottomAnchor="0.0"
          AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
        <Label text="Look - reusable Tab contents!"/>
        <Button fx:id="btnTestController" mnemonicParsing="false" text="Test Controller"/>
        <padding>
            <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
        </padding>
    </VBox>
</AnchorPane>




控制器:

MainController.java:

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;

import java.io.IOException;

public class MainController {

    @FXML
    private TabPane tabPane;
    @FXML
    private Tab tab1;
    @FXML
    private Tab tab2;
    @FXML
    private Tab tab3;

    @FXML
    private void initialize() {

        // Our TabPane has 3 Tabs. Let's populate them with content, reusing our TabContent.fxml file
        setTabContent(tab1, new Tab1Controller());
        setTabContent(tab2, new Tab2Controller());
        setTabContent(tab3, new Tab3Controller());

    }

    /**
     * Sets the content of Tab to the TabContent.fxml document
     *
     * @param tab        The Tab whose content we wish to set
     * @param controller The controller for this particular Tab's content
     */
    private void setTabContent(Tab tab, TabController controller) {

        // Load our TabContent.fxml file and set it as the content of the Tab that was passed to this method
        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("TabContent.fxml"));

            // Set the controller for this specific tab
            loader.setController(controller);

            // Set the content of the passed Tab to this FXML content
            tab.setContent(loader.load());
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

Tab1Controller:

import javafx.fxml.FXML;
import javafx.scene.control.Button;

public class Tab1Controller implements TabController {

    @FXML
    private Button btnTestController;

    @FXML
    private void initialize() {

        // Set our button to print out which controller is being used
        btnTestController.setOnAction(event -> System.out.println("Hello, from Controller #1!"));

    }
}

只需复制此控制器再多两次 Tab2Controller.java 和`Tab3Controller.java

Just duplicate this controller two more times for Tab2Controller.java and `Tab3Controller.java


结果:

点击测试控制器按钮将打印出 Hello,来自控制器#2!,确认每个Tab的内容由他们自己的控制器控制。

Clicking on the Test Controller button will print out Hello, from Controller #2!, confirming each Tab's contents are controlled by their own controller.

这篇关于JavaFX可重用FXML代码段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆