将自定义类型的FXML属性设置为自定义javafx组件的属性

时间:2017-10-10 09:11:45

标签: java javafx javafx-8

我按http://docs.oracle.com/javafx/2/fxml_get_started/custom_control.htm

中所述创建了自定义JavaFX组件
// Component.fxml
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.VBox?>
<fx:root type="javafx.scene.layout.VBox" xmlns:fx="http://javafx.com/fxml">
    <Label fx:id="label"/>
</fx:root>

// Component.java
public class Component extends VBox {

    private final Entity entity;
    @FXML private Label label;

    public Component(@NamedArg("entity") Entity entity) {
        this.entity = entity;
        FXMLLoader fxmlLoader = new FXMLLoader();
        fxmlLoader.setLocation(Component.class.getResource("/Component.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);

        try {
            fxmlLoader.load();
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }

    @FXML
    private void initialize() {
        label.textProperty().set(this.entity.toString());
    }
}

现在我将它导入根布局(自定义组件)。

// Root.fxml
<?xml version="1.0" encoding="UTF-8"?>

<?import foo.bar.javafx.Component?>
<?import javafx.scene.layout.AnchorPane?>
<fx:root type="javafx.scene.layout.AnchorPane"xmlns:fx="http://javafx.com/fxml">
// TODO How to pass entity?
<Component entity=?>
</Component>

// Root.java
public class Root extends AnchorPane {

    public Root() {
        FXMLLoader fxmlLoader = new FXMLLoader();
        fxmlLoader.setLocation(Root.class.getResource("/Root.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);

        try {
            fxmlLoader.load();
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }

}

如何将实体传递给Component? 我知道如何传递String - 它只是<Component entity="text">。但如何通过仲裁类的实例? 附:不想为此使用Singleton模式。

1 个答案:

答案 0 :(得分:2)

您的问题的解决方案可能是将组件与控制器分开,例如为每个控制器创建一个Controller类: 虽然组件是VBox,但您可以为它定义.fxml,如:

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

<?import javafx.scene.layout.VBox?>
<VBox xmlns="http://javafx.com/javafx"
      xmlns:fx="http://javafx.com/fxml"
      fx:controller="stackoverflow.one.ComponentController">

</VBox>

它是包含实体的控制器:

public class ComponentController implements Initializable{

    private Entity entity;

    @Override
    public void initialize(URL location, ResourceBundle resources) {

    }

    public Entity getEntity() {
        return entity;
    }

    public void setEntity(Entity entity) {
        this.entity = entity;
    }
}

您也可以像这样更改Roor:

<?import javafx.scene.layout.AnchorPane?>
<AnchorPane xmlns="http://javafx.com/javafx"
            xmlns:fx="http://javafx.com/fxml"
            fx:controller="stackoverflow.one.RootController">
    <fx:include source="ComponentController.java" fx:id="component"/>

</AnchorPane>

然后在控制器中,您可以获得ComponentController的引用,并且您可以设置您从服务获得的实体。

public class RootController implements Initializable {

    @FXML
    private ComponentController componentController;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // getting Entity from a service or from any other sources
        //You may replace this line with an appropriate one for you.
        Entity entity = getEntity();
        componentController.setEntity(entity);
    }
}

现在您已经分离了控制器和视图组件,您甚至不需要加载它们,因为FXMLLoader为您完成了它。 这将是如何将对象传递给另一个视图的控制器的基本概念。