简体   繁体   中英

Set FXML properties of custom type as attributes for custom javafx component

I created custom JavaFX component as described in http://docs.oracle.com/javafx/2/fxml_get_started/custom_control.htm .

// 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());
    }
}

Now i import it into root layout (custom component too).

// 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);
        }
    }

}

How can i pass entity to Component? I know how to pass String - it's just <Component entity="text"> . But how to pass instance of arbitary class? PS Don't want to use Singleton pattern for this.

The solution for your problem could be that to separate the components from the controller like creating a Controller class for each of your controller: While the component is a VBox you can define an .fxml for it like:

<?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>

It's controller which contains an entity:

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;
    }
}

You can also change the Roor like this:

<?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>

Then in the controller you can get a reference of the ComponentController and you can set the entity, that you got from a service for example.

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);
    }
}

Now you have separated the controllers and the view-components, you don't even need to load them because the FXMLLoader does it for you. This would be the basic concept how to pass an object to another view's controller.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM