Помимо использования фабричного метода, например , описанного fabian , вы можете использовать механизм компоновщика для этого. Как и в случае <fx:factory>
, который ограничен методами static
без аргументов, использование немного ограничено. Однако вот пример фабрики / компоновщика, который создает TextField
или Label
, в зависимости от того, установлен ли флаг editable
:
package org.jamesd.examples.fxmlfactory;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.util.Builder;
public class Factory implements Builder<Node> {
private String text = "" ;
private boolean editable = false ;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public boolean isEditable() {
return editable;
}
public void setEditable(boolean editable) {
this.editable = editable;
}
@Override
public Node build() {
if (editable) {
return new TextField(text);
} else {
return new Label(text);
}
}
}
Вот файл F XML, который использует this:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.BorderPane ?>
<?import javafx.scene.layout.HBox ?>
<?import javafx.scene.Node ?>
<BorderPane xmlns="http://javafx.com/javafx/11.0.1"
xmlns:fx="http://javafx.com/fxml/1">
<center>
<HBox spacing="5">
<Node text="Hello" editable="false" />
<Node text="Name" editable="true" />
</HBox>
</center>
</BorderPane>
Чтобы FXMLLoader
знал о вашем сборщике, вы должны указать класс, для которого он будет использоваться. Здесь мы можем использовать его для Node
(но это требование немного ограничительно, так как вы будете существенно ограничены одним компоновщиком). Вы делаете это, создавая BuilderFactory
реализацию:
package org.jamesd.examples.fxmlfactory;
import javafx.fxml.JavaFXBuilderFactory;
import javafx.scene.Node;
import javafx.util.Builder;
import javafx.util.BuilderFactory;
public class NodeBuilderFactory implements BuilderFactory{
private final JavaFXBuilderFactory defaultFactory = new JavaFXBuilderFactory();
public Builder<?> getBuilder(Class<?> type) {
if (type == Node.class) {
return new Factory();
}
return defaultFactory.getBuilder(type);
}
}
и затем регистрируя ее с помощью FXMLLoader
:
package org.jamesd.examples.fxmlfactory;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class App extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("Example.fxml"));
loader.setBuilderFactory(new NodeBuilderFactory());
Parent root = loader.load();
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}