Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add children component and new attribute to custom JavaFX control?

I want to create a new JavaFX component and use it in FXML. How can I define the possibility of usage and types of children for this component? And is there a way to create my own atrributes for this component? As example, this is what I want to get:

<MyNewComponent specificAttribute="...">
   <children>
      <SpecificChildren></SpecificChildren>
   </children>
</MyNewComponent>
like image 950
Eugene Avatar asked Jun 15 '13 09:06

Eugene


1 Answers

When you set the value of an attribute or specify a child value in FXML you are basically just setting properties on the object. Usually attributes are used for simple scalar values and nesting values is used for setting more complex values.

When the FXML parser encounters a lower case attribute or tag it assumes the value is a property and will try to set it on the specific object.

As an example consider a custom class that derives from the Parent class and overrides the getChildren() method so that it is part of the controls public API.

public class MyNewComponent extends Parent {

    @Override
    public ObservableList<Node> getChildren() {
        return super.getChildren();
    }
}

You should now be able to add other controls directly to your custom control in FXML like this.

<MyNewComponent>
    <children>
        <SpecificChildren></SpecificChildren>
    <children>
</MyNewComponent> 

Which is conceptually similar to the following Java code:

myNewComponent.getChildren().add(new SpecificChildren());

You can improve this further by decorating your custom control class with the DefaultProperty annotation like this:

@DefaultProperty(value = "children")
public class MyNewComponent extends Parent {

This allows you to omit the <Children></Children> tags so your FXML can be updated to look like this.

<MyNewComponent>
    <SpecificChildren></SpecificChildren>
</MyNewComponent>

Note that this adds the control to the scene graph but may not actually display the control where you want it to as you have not told it how to do so (you will have to provide an implementation for some of the layout methods or derive from a class that already has layout logic such as VBox).

similarly, attributes can be defined like this.

@DefaultProperty(value = "children")
public class MyNewComponent extends Parent {

    @Override
    public ObservableList<Node> getChildren() {
        return super.getChildren();
    }

    public String setSpecificAttribute(String str) {
        // Do something here...
    }
}

And then in your FXML:

<MyNewComponent specificAttribute = "ABC123">

Which is conceptually similar to:

myNewComponent.setSpecificAttribute("ABC123");

Please refer to the official FXML reference for further details as there are some exceptions to the above advice depending on the type of value you are trying to set and may require some additional code to get it working.

like image 139
Benjamin Gale Avatar answered Oct 31 '22 22:10

Benjamin Gale