My last post was about finding or developing a library in which a handler could create and bind automatically fields of some JavaBean to the JavaFx view.
Last post's link.
I've created a project as prototype of this feature. It's called FXControlCreator, and it can be found at GitHub here. Today I'm gonna describe what is developed there, how it works and what I'm gonna do next. I worked with Netbeans 8.0 and Java 8.
What I wanted when I started this project was a way to define an annotation to a JavaBean property. This annotation would be read by a handler and this handler would create at runtime the JavaFx controls to the view. So, lets see what I've done until now.
The first thing I'm gonna show is the annotation I abstracted. It's called FXControl.
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface FXControl {
String label() default "";
Class<? extends WhenCreate>[] when() default {Ever.class};
Class<? extends ControlFactory> factory();
}
- label: it describes the text that fits as a label for the control created at the view.
- when: it describes when the handler must create the control. The default option is Ever.class. You can create other options by adding some interface that inherits WhenCreate, for example: InModeMaintenance.class, InModeView.class, etc.
- factory: it describes the implementation of ControlFactory. This implementation is responsible for instanciate the control.
public interface ControlFactory<T extends Control, P extends Property> {
T createFor(P property);
}
The base structure of the feature is an interface called ViewHandler, it describes the method handleControlCreation. This method recieves a PaneHandler, a WhereCreate class, and the java objects.
public interface ViewHandler {
void handleControlCreation(PaneHandler handler, Class<? extends WhenCreate> when, Object... objects);
}
-PaneHandler: It's an interface that describes how the handler will add a new control inside.
public interface PaneHandler {
void addControl(FXControl annotation, Property property) throws CanNotInstanceControlCreator;
}
So, that's all the structure of the project until now. Lets see an sample implementation of the responsabilities described above.I created a class called TestProperty, and above the getter of it's property I defined the FxControl annotation. At the annotation I informed the control factory TextFieldFactory and it's label.
public class TestProperty {
protected StringProperty property;
public TestProperty() {
this.property = new SimpleStringProperty();
}
public String getText() {
return property.get();
}
@FXControl(label = "Text Property" , factory = TextFieldFactory.class)
public StringProperty getProperty() {
return property;
}
}
At my view controller I called an implementation of the ViewHandler to create the controls for the TestProperty object at initialize method. The handler was GridPaneViewHandler, because the main pane of my window was a GridPane.I included a button in which I could test if the binding between the control and the property was working fine, and I defined the handleButtonAction as the action event of this button.
public class FXMLController implements Initializable {
@FXML
private Label label;
@FXML
private GridPane pane;
private TestProperty test = new TestProperty();
@FXML
private void handleButtonAction(ActionEvent event) {
label.setText(test.getText());
}
@Override
public void initialize(URL url, ResourceBundle rb) {
new GridPaneViewHandler().handleControlCreation(new GridPaneHandler(pane), Ever.class, test);
}
}
And this was the result. We can see that the automact creation of the TextField and it's label worked fine.
When I type something inside the control and click at the button, the label below the button shows what I type. So the binding worked fine too.
That's all until now folks! I've got already some things to develop subsequently.
- I'll find a way to pass atribute details to the control factory. For example, the width of the TextField.
- I'll implement new features to factoring controls and handling views.
Thank you for read my post. I hope you like it and, please, comment.
Bye!