0

我想为我的文件创建一个自定义tag/但我不希望这个元素被强制从 a 、、等继承。是否有一些接口可以在我的自定义元素中实现,这需要我实现让我们说返回一个/元素所需的方法,该元素应该在. 如果可能发生以下情况,我的意思是什么?elementfxmlPaneButtonTextFieldfx()NodeRegionScene

public class CustomElement implements SOME_FXML_INTERFACE {

    private String myArg;

    public CustomElement(@NamedArg("myArg") myArg) {
        this.myArg = myArg;
    }

    // method that is required to be implemented by SOME_FXML_INTERFACE
    // this method retuns some GUI element which actually needs to be rendered in the Scene
    @Override
    public Object fx() {
        return new TextField(myArg);
    }

}


<HBox>
    <CustomElement myArg="some_argument"/>
</HBox>

这一切都是为了让我有CustomElement谁能接受构造函数中的自定义参数。

4

2 回答 2

1

您可以创建任意对象,但工厂对象只能由支持此功能的节点使用。(从技术上讲,您可以这样做,但它会涉及使用 getter 在每次调用它时返回一个新实例。)但是,您可以例如使用您的自定义类cellFactory作为ListView.

如果您不需要依赖实例方法,但对static工厂方法感到满意,您可以使用fx:factory标签指定创建节点实例的方法,您无需实现任何接口即可:

package my.package;

...

public class CustomElement {

    public static Node fx() {
        return new TextField(myArg);
    }

}
<?import my.package.CustomElement?>
<?import javafx.scene.layout.HBox?>

<HBox xmlns:fx="http://javafx.com/fxml">
    <children>
        <CustomElement fx:factory="fx" />
    </children>
</HBox>

FXML 简介中提供了更多信息

顺便说一句:如果您的类有一个public不带任何参数的构造函数,您只需将具有类名称的元素添加到 fxml 即可创建该类的实例。例如,以下 fxml 会导致ArrayList加载时;但是,您可以使用这些实例的方式是有限的;

<?import java.util.ArrayList?>

<ArrayList />
于 2020-03-13T19:47:30.787 回答
0

除了使用fabian 所描述的工厂方法外,您还可以重新利用构建器机制来执行此操作。与 一样<fx:factory>,它仅限于static没有参数的方法,用法有点受限。TextField但是,这是一个创建 a或 a的示例工厂/构建器Label,具体取决于是否editable设置了标志:

package org.jamesd.examples.fxmlfactory;

import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.util.Builder;

public class Factory implements Builder<Node> {

    private String text = "" ;
    private boolean editable = false ;



    public String getText() {
        return text;
    }



    public void setText(String text) {
        this.text = text;
    }



    public boolean isEditable() {
        return editable;
    }



    public void setEditable(boolean editable) {
        this.editable = editable;
    }



    @Override
    public Node build() {
        if (editable) {
            return new TextField(text);
        } else {
            return new Label(text);
        }
    }


}

这是一个使用它的 FXML 文件:

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

<?import javafx.scene.layout.BorderPane ?>
<?import javafx.scene.layout.HBox ?>
<?import javafx.scene.Node ?>


<BorderPane xmlns="http://javafx.com/javafx/11.0.1"
    xmlns:fx="http://javafx.com/fxml/1">

    <center>
        <HBox spacing="5">
            <Node text="Hello" editable="false" />
            <Node text="Name" editable="true" />
        </HBox>
    </center>
</BorderPane>

为了让FXMLLoader你的构建器知道,你必须指定一个类来使用它。在这里我们可以使用它Node(但这个要求有点限制,因为你基本上仅限于单个构建器)。您可以通过创建一个BuilderFactory实现来做到这一点:

package org.jamesd.examples.fxmlfactory;

import javafx.fxml.JavaFXBuilderFactory;
import javafx.scene.Node;
import javafx.util.Builder;
import javafx.util.BuilderFactory;

public class NodeBuilderFactory implements BuilderFactory{

    private final JavaFXBuilderFactory defaultFactory = new JavaFXBuilderFactory();

    public Builder<?> getBuilder(Class<?> type) {
        if (type == Node.class) {
            return new Factory();
        }
        return defaultFactory.getBuilder(type);
    }

}

然后将其注册到FXMLLoader

package org.jamesd.examples.fxmlfactory;

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

public class App extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {

        FXMLLoader loader = new FXMLLoader(getClass().getResource("Example.fxml"));
        loader.setBuilderFactory(new NodeBuilderFactory());
        Parent root = loader.load();
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

}
于 2020-03-13T20:14:36.637 回答