我可以将对象的实例存储在 javaFX 节点中吗?

Can I store instance of an object in a javaFX node?

我有一个 JavaFX 应用程序,从主 window 作为 TabPane 对象开始。 在那个 TabPane 中,我有一个特定的 Tab,它包含一个 Button 对象,可以向主 TabPane 添加新的选项卡。但是我需要将主 TabPane 中的每个 Tab 与单个对象实例纠缠在一起(每个选项卡应该与 class Merchant 的一个实例一起使用)

class Merchant 有一些方法 createSortiment() 根据 Merchant 对象的参数生成 ArrayList 随机选择的项目。

主控制器 GUIController 控制主 window,另一个控制器 GUIMerchantTabController 控制选项卡。

我需要能够添加一个新选项卡(我可以做到)并以某种方式将其绑定到 Merchant JohnSmith = new Merchant(); 然后我需要控制器 GUIMerchantTabController 能够响应一个动作带有 fx:id="createSortiment" 的按钮事件调用 JohnSmith.createSortiment()(我不知道该怎么做)并将每个生成的项目添加到 Tab 中的某些 Accordion 作为TitledPane(我也能做到)。

我的主要问题:

如何将 JohnSmith 的实例保存到特定 Tab 中,GUIMerchantTabController 将能够使用 John 的方法并访问他的数据? 可能是某种对象实例引用吗?我可以以某种方式将对象作为节点添加到该窗格吗? Java 中是否存在某些 "data" 属性(如 HTML <element data-storeSomething="Some text here, or json object">)?

我认为没有必要查看我的文件,但为了更好的想法,这些是我的 fmxls...

商家标签的FXML:

<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.Accordion?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.text.Font?>


<Tab fx:controller="damn.fuck.shit.GUIMerchantTabController" closable="false" text="Merchant name" xmlns:fx="http://javafx.com/fxml/1">
    <content>
        <AnchorPane prefHeight="200.0" prefWidth="200.0">
            <children>
                <SplitPane dividerPositions="0.7508361204013378" prefHeight="371.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
                    <items>
                        <ScrollPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
                            <Accordion fx:id="sortimentViewSpace" prefHeight="369.0" prefWidth="438.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
                                <panes>
                                    <TitledPane animated="false" text="Item00">
                                        <content>
                                            <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
                                                <Label text="This is testing item label lol" />
                                            </AnchorPane>
                                        </content>
                                    </TitledPane>
                                </panes>
                            </Accordion>
                        </ScrollPane>
                        <ScrollPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
                            <Button fx:id="createSortimentButton" layoutX="51.0" layoutY="-338.0" mnemonicParsing="false" onAction="#generateSortiment" prefHeight="31.0" prefWidth="142.0" text="Vytvoř sortiment" textAlignment="CENTER" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
                                <font>
                                    <Font name="System Bold" size="14.0" />
                                </font>
                            </Button>
                        </ScrollPane>
                    </items>
                </SplitPane>
            </children>
        </AnchorPane>
    </content>
</Tab>

主要的 FXML window:

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Accordion?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.FlowPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.text.Font?>

<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.cell.ChoiceBoxListCell?>
<TabPane fx:id="mainWindow" maxHeight="400.0" maxWidth="600.0" minHeight="400.0" minWidth="600.0" prefHeight="400.0" prefWidth="600.0" tabClosingPolicy="UNAVAILABLE" xmlns="http://javafx.com/javafx/8.0.112" xmlns:fx="http://javafx.com/fxml/1" fx:controller="damn.fuck.shit.GUIController">
  <tabs>

    <Tab closable="false" text="Volby">
         <content>
            <Pane prefHeight="200.0" prefWidth="200.0">
               <children>
                  <FlowPane hgap="5.0" layoutX="0.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="371.0" prefWidth="300.0" vgap="5.0">
                     <children>
                        <Label alignment="CENTER" prefHeight="25.0" prefWidth="307.0">
                            <font>
                                <Font name="System Bold" size="14.0" />
                            </font>
                            <text>
                                    Vytvoř nového kupce
                            </text>
                        </Label>
                         <Label prefHeight="25.0" prefWidth="40.0" text="Jméno:" />
                         <TextField prefHeight="25.0" prefWidth="235.0" promptText="Vepiš jméno nového kupce" />
                        <CheckBox mnemonicParsing="false" prefHeight="25.0" prefWidth="115.0" text="Prodává magicé předměty" />
                         <Button fx:id="createMerchantButton" prefHeight="25.0" prefWidth="150.0" text="Vytvoř nového kupce" onAction="#addMerchantTab">

                         </Button>
                     </children>
                     <opaqueInsets>
                        <Insets />
                     </opaqueInsets>
                     <padding>
                        <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
                     </padding>
                  </FlowPane>
               </children>
            </Pane>
         </content></Tab>
  </tabs>
</TabPane>

节点有一个 userData API:

public void setUserData(Object value) 

Convenience method for setting a single Object property that can be retrieved at a later date. This is functionally equivalent to calling the getProperties().put(Object key, Object value) method. This can later be retrieved by calling getUserData().

它还有一个属性 API 用于关联键->值对的映射:

public final ObservableMap<Object,Object> getProperties()

Returns an observable map of properties on this node for use primarily by application developers.

这两个 API 都允许您将用户对象实例与 JavaFX 节点相关联。

或者,您可以扩展您正在使用的任何节点类型(只要它不是最终的,很多东西都是最终的并且在 JavaFX 中不是用户可扩展的),并在您的扩展中存储一个引用。例如:

class MyTab extends Tab {
    private MyClass myObject;

    public MyTab(MyClass myObject) {
        super();
        this.myObject = myObject;
    }
}

使用 class 扩展的优点是可以保留类型信息,以备您的应用从中受益。