JavaFXML创建不扩展节点的自定义标记元素
我想为我的JavaFXML创建不扩展节点的自定义标记元素,java,javafx,javafx-8,javafx-2,fxml,Java,Javafx,Javafx 8,Javafx 2,Fxml,我想为我的fxml文件创建一个自定义标记/元素,但我不想强制此元素从窗格、按钮、文本字段等继承。在我的自定义元素中是否有一些可以实现的接口需要我实现,比如说fx()方法,该方法需要返回一个节点/区域元素,该元素应该在场景中渲染。我的意思是 如果有可能做到以下几点 public class CustomElement implements SOME_FXML_INTERFACE { private String myArg; public CustomElement(@Name
fxml
文件创建一个自定义标记
/元素
,但我不想强制此元素从窗格
、按钮
、文本字段
等继承。在我的自定义元素中是否有一些可以实现的接口需要我实现,比如说fx()
方法,该方法需要返回一个节点
/区域
元素,该元素应该在场景
中渲染。我的意思是
如果有可能做到以下几点
public class CustomElement implements SOME_FXML_INTERFACE {
private String myArg;
public CustomElement(@NamedArg("myArg") myArg) {
this.myArg = myArg;
}
// method that is required to be implemented by SOME_FXML_INTERFACE
// this method retuns some GUI element which actually needs to be rendered in the Scene
@Override
public Object fx() {
return new TextField(myArg);
}
}
<HBox>
<CustomElement myArg="some_argument"/>
</HBox>
public类CustomElement实现了一些\u FXML\u接口{
私有字符串myArg;
公共CustomElement(@NamedArg(“myArg”)myArg){
this.myArg=myArg;
}
//方法,该方法需要由某些\u FXML\u接口实现
//此方法重新运行一些实际需要在场景中渲染的GUI元素
@凌驾
公共对象fx(){
返回新的文本字段(myArg);
}
}
所有这些都是为了让
CustomElement
可以接受构造函数中的自定义参数。您可以创建任意对象,但factory对象只能由支持此功能的节点使用。(从技术上讲,您可以这样做,但这需要使用getter在每次调用它时返回一个新实例。)但是,您可以使用自定义类作为cellFactory
,用于ListView
如果您不需要依赖实例方法,但对static
factory方法感到满意,则可以使用fx:factory
标记指定创建节点实例的方法,而无需实现任何接口:
package my.package;
...
public class CustomElement {
public static Node fx() {
return new TextField(myArg);
}
}
更多信息可在
顺便说一句:如果你的类有一个不带任何参数的public
构造函数,你只需在fxml中添加一个带有类名称的元素,就可以创建该类的实例。例如,加载时,以下fxml会导致ArrayList
;但是,您可以使用这些实例的方式是有限的
以及使用工厂方法,您可以重新调整生成器机制的用途来实现这一点。与
一样,它仅限于不带参数的静态方法,使用有点有限。但是,下面是一个示例工厂/生成器,它创建一个文本字段
或标签
,具体取决于是否设置了可编辑
标志:
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);
}
}
}
然后将其注册到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);
}
}
您希望返回什么节点而不是扩展节点?我已将fx()
返回类型更改为Object
,因为它不会以以前编写的方式编译。我不想扩展节点,因为这会带来节点的开销属性/方法,而我不会使用这些属性/方法。@SamOrozco有很多很好的理由选择聚合而不是继承。例如,您可能不想提交您要返回的节点类型(允许在更高版本中从一种节点类型更改为另一种,并确保没有代码会中断);或者,您可能希望根据某些条件返回不同类型的节点。子类化特定节点将不允许您这样做;子类化节点
本身不允许您,例如,提供文本字段
。
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);
}
}