【问题标题】:JavaFX: How to create 5x identical Tabs within a TabPane with SceneBuilder, without 5x work?JavaFX:如何使用 SceneBuilder 在 TabPane 中创建 5x 相同的选项卡,而无需 5x 工作?
【发布时间】:2017-01-29 11:35:58
【问题描述】:

如何使用 SceneBuilder 创建 5x 相同的 TabPane,而无需 5x 工作?

  • 一个窗口包含 5 个相同的 TabPane,具有非常多且复杂的 GUI 组件
  • 我也想用SceneBuilder来设计窗口/标签
  • 如何避免使用 SceneBuilder 设计 5 倍相同的 TabPane,尽管只有 fx: id 和 handle 方法 名称略有不同,例如:
    TabPane0:tab0_textField_inputValue
    TabPane1:tab1_textField_inputValue
    TabPane2:tab2_textField_inputValue
    等等。

解决办法:

  • 只需使用 SceneBuilder 设计一个 TabPane
  • 但是如何复制这个“主”-TabPane 仍然是 4 倍,从而自动调整变量/方法名称?
  • 副本应该是自动的,因为我经常需要它(在每个 GUI 开发步骤之后或 “主”标签的更正/调整)
  • 是否可能已经有一个工具可以相应地自动扩展 FXML 文件?

【问题讨论】:

    标签: user-interface javafx scenebuilder


    【解决方案1】:

    您通常会创建一个仅包含一个 TabPane 的 fxml,并使用 <fx:include> 多次使用此 fxml:

    tabpane.fxml

    <TabPane xmlns:fx="http://javafx.com/fxml/1" fx:controller="mapackage.TabPaneController">
        ...
    </TabPane>
    

    包含布局

    <VBox xmlns:fx="http://javafx.com/fxml/1" fx:controller="mapackage.RootController">
        <children>
            <fx:include fx:id="tabPane1" source="@tabpane.fxml" />
            <fx:include fx:id="tabPane2" source="@tabpane.fxml" />
            ...
        </children>
    </VBox>
    
    public class RootController {
        @FXML
        private TabPaneController tabPane1Controller;
        @FXML
        private TabPaneController tabPane2Controller;
        ...
    }
    

    当然,您应该确保TabPaneController 包含适当的方法来访问您需要从RootController 访问的功能...

    【讨论】:

    • 谢谢。而不是 'source ="@tabpane.fxml" ' 使用 'source ="tabpane.fxml" ' 可能更好。
    【解决方案2】:

    解决方案:
    谢谢你的帮助。我的解决方案如下:
    - 我多次使用 TabView.fxml 进行输入
    - 用户单击选项卡后,每个选项卡都必须分配一个唯一的 tabId
    - 下面的代码是完整的和工作的

    Main.java

    public class Main extends Application { 
        @Override
        public void start(Stage primaryStage) throws Exception {
            Scene scene = new Scene(new AnchorPane());
            FXMLLoader loader = new FXMLLoader(getClass().getResource("tabPaneRootView.fxml"));
            scene.setRoot(loader.load());
            TabPaneRootController controller = loader.getController();
            controller.myInit(); //my init-Methode 
            primaryStage.setScene(scene);
            primaryStage.setTitle("I'm Tab x"); 
            primaryStage.show();
        }
    
        public static void main(String[] args) {            
            launch(args);
        }   
    }
    

    TabPaneRootController.java

    public class TabPaneRootController {    
        @FXML private TabPane tabPane;
    
        //################################# Inject SubController ################################## 
        //Inject tab controller
        @FXML private TabController xxx_tab1_xxxController; //TabPaneRootView.fxml_include_fx:id="xxx_tab_xxx" + "Controller"
        @FXML private TabController xxx_tab2_xxxController;
        //#########################################################################################
    
        public void myInit() {      
            tabPane.getSelectionModel().selectedItemProperty().addListener((ObservableValue<? extends Tab> observable,
                    Tab oldValue, Tab newValue)->{
                        preparationInitTab(newValue);                   
                    });
        }
    
        public void preparationInitTab(Tab selectedTab) {
            String currentTabId_string = selectedTab.getId();
            String[] parts = currentTabId_string.split("_");
            int currentTabId = Integer.parseInt(parts[1]); 
    
            switch(currentTabId) {
            case 1:
                xxx_tab1_xxxController.initTab(currentTabId);
                break;
            case 2:
                xxx_tab2_xxxController.initTab(currentTabId);
                break;
    
            default:
                System.out.println("Warning: Select an unassigned tab='" + currentTabId + "'");
            }
        }       
    }
    

    TabController.java

    public class TabController {    
        private int tabId = -9; //is the ID of the currently selected tab
    
        @FXML private TextField tab_textField_currentTabName;
        @FXML private TextField tab_textField01_costPosition1;
    
        public void initTab(int currentTabId) {
            System.out.println(">TabController::initTab() with currentTabId=" + currentTabId);
            this.tabId = currentTabId;      
            tab_textField_currentTabName.setText(String.valueOf(tabId));
        }
    
        //----------------- FXML-Methoden --------------------------    
        @FXML
        private void handleTabTextFieldCostPosition1() {
            System.out.println("costPosition1[" + tabId + "]=" + tab_textField01_costPosition1.getText());
        }
    
        @FXML
        private void handleExit() {     
            Platform.exit();
        }
    }
    

    tabPaneRootView.fxml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.control.Label?>
    <?import javafx.scene.control.Tab?>
    <?import javafx.scene.control.TabPane?>
    <?import javafx.scene.layout.AnchorPane?>
    
    <AnchorPane xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.myapp.TabPaneRootController">
       <children>
          <TabPane fx:id="tabPane" tabClosingPolicy="UNAVAILABLE">
            <tabs>
                <Tab fx:id="tabId_0" text="Tab0">
                   <content>
                      <AnchorPane prefHeight="200.0" prefWidth="200.0">
                         <children>
                            <Label layoutX="10.0" layoutY="30.0" text="general information ..." />
                         </children>
                      </AnchorPane>
                   </content>
                </Tab>
                <Tab fx:id="tabId_1" text="Tab1">
                   <content>
                      <fx:include source="tabView.fxml" fx:id="xxx_tab1_xxx" />
                   </content>
                </Tab>
                <Tab fx:id="tabId_2" text="Tab2">
                   <content>
                      <fx:include source="tabView.fxml" fx:id="xxx_tab2_xxx" />             
                   </content>
                </Tab>
            </tabs>
          </TabPane>
       </children>
    </AnchorPane>
    

    tabView.fxml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.control.Button?>
    <?import javafx.scene.control.Label?>
    <?import javafx.scene.control.TextField?>
    <?import javafx.scene.layout.AnchorPane?>
    
    <AnchorPane prefHeight="200.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.myapp.TabController">
       <children>
          <Label layoutX="10.0" layoutY="40.0" text="I'm Tab Index:"> </Label>
          <TextField fx:id="tab_textField_currentTabName" editable="false" layoutX="107.0" layoutY="35.0" prefWidth="30.0" />
          <Button alignment="CENTER" contentDisplay="CENTER" layoutX="185.0" mnemonicParsing="false" onAction="#handleExit" text="Exit" AnchorPane.bottomAnchor="10.0"> </Button>
          <Label layoutX="10.0" layoutY="90.0" text="costPosition1 in € =" />
          <TextField fx:id="tab_textField01_costPosition1" alignment="CENTER_RIGHT" layoutX="150.0" layoutY="85.0" onKeyReleased="#handleTabTextFieldCostPosition1" prefWidth="150.0" promptText="input an int value" />
       </children>
    </AnchorPane>
    

    - Directory structure
    - Example started

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-16
      • 2020-03-03
      • 2011-10-17
      • 2019-02-25
      • 2017-01-28
      • 2013-01-02
      • 2016-09-14
      • 2017-07-04
      相关资源
      最近更新 更多