Reputation: 5353
As said in the title I want to specialize the usage of a TableView that I will reuse many time, that speciazation contains :
I use raw FXML files and Controller, no UI drag and drop building.
In order to keep the usage of my component the easiest possible I would like to hide the component part of JavaFX and only allow my methods, how to do it ?
Upvotes: 0
Views: 121
Reputation: 82461
Create a class extending Control
. Add the methods you want the user to access to this class.
Create a skin for this class and implement the behavior you don't want the user to access there.
Benefits:
public class MyControl extends Control {
@Override
protected Skin<?> createDefaultSkin() {
return new MyControlSkin(this);
}
private final StringProperty text = new SimpleStringProperty();
public final String getText() {
return this.text.get();
}
public final void setText(String value) {
this.text.set(value);
}
public final StringProperty textProperty() {
return this.text;
}
}
public class MyControlSkin extends SkinBase<MyControl> {
public MyControlSkin(MyControl control) {
super(control);
Text text = new Text();
text.textProperty().bind(control.textProperty());
getChildren().setAll(text);
}
}
@Override
public void start(Stage primaryStage) {
final MyControl control = new MyControl();
Button btn = new Button("Say 'Hello World'");
btn.setOnAction((ActionEvent event) -> {
control.setText("Hello World!");
});
Scene scene = new Scene(new VBox(10, btn, control));
primaryStage.setScene(scene);
primaryStage.show();
}
Note that it does not matter how you create the UI. It could be directly created from java or loaded from fxml - this does not matter. You could e.g. use the skin as fxml controller and root:
<fx:root type="javafx.scene.control.SkinBase" xmlns:fx="http://javafx.com/fxml">
<children>
<Text fx:id="text"/>
</children>
</fx:root>
@FXML
private Text text;
public MyControlSkin(MyControl control) throws IOException {
super(control);
getChildren().clear();
FXMLLoader loader = new FXMLLoader(someUrl);
loader.setRoot(this);
loader.setController(this);
loader.load();
text.textProperty().bind(control.textProperty());
}
BTW: The duplicate filtering would IMHO be better of in a seperate class, like a TransformationList
. This way you could reuse the behavior independent of the UI which would allow easier reuse (e.g. For use with a ListView
).
Upvotes: 2
Reputation: 5353
Here is the current way I found to do it use an interface an use that interface when using @FXML
injection.
My specialized components :
public class EquipmentTableView extends AnchorPane implements IEquipmentTableView{[...]}
Where AnchorPane
is from JavaFX
and the interface from me.
The FXML of the component :
<fx:root type="javafx.scene.layout.AnchorPane" xmlns:fx="http://javafx.com/fxml">
<TableView fx:id="tableView"
AnchorPane.topAnchor="0.0" AnchorPane.bottomAnchor="0.0"
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
</TableView>
</fx:root>
The FXML to include the component :
<EquipmentTableView fx:id="tableView"/>
The injection in the controller
public class ReadController {
// use the interface here
@FXML private IEquipmentTableView tableView;
public static String FXML="read.fxml";
public static String TITLE_KEY="read.title";
@FXML
void initialize(){
tableView.addAll(Arrays.asList(
new Equipment("name1", "partNumber1", "MFC1", "00000000001", "3400000000000001"),
new Equipment("name2", "partNumber2", "MFC2", "00000000002", "3400000000000002"),
new Equipment("name3", "partNumber3", "MFC3", "00000000003", "3400000000000003")));
}
}
To sum it up :
TableView
inside the components instead of inheriting it I don't allow to manipulate the TableView
. I inherit AnchorPane instead because I want my table view to auto-resize, you can inherits from Pane otherwise.Upvotes: 1