如何扩展使用FXML的自定义JavaFX组件

如何扩展使用FXML的自定义JavaFX组件,java,inheritance,javafx,fxml,Java,Inheritance,Javafx,Fxml,如果自定义JavaFX组件使用FXML作为视图,如何正确扩展该组件以添加或修改其GUI组件 作为示例场景,假设我使用以下方法创建自定义JavaFX组件: SpecializedButton.java(控制器) SpecializedButton.fxml(视图) SpecializedButton类加载FXML视图(SpecializedButton.FXML)并充当其控制器 SpecializedButtonFXML视图只创建了一个HBox,它的左右两侧分别有两个锚烷和一个标签和按钮。单击按钮

如果自定义JavaFX组件使用FXML作为视图,如何正确扩展该组件以添加或修改其GUI组件

作为示例场景,假设我使用以下方法创建自定义JavaFX组件:

SpecializedButton.java(控制器)

SpecializedButton.fxml(视图)

SpecializedButton类加载FXML视图(SpecializedButton.FXML)并充当其控制器

SpecializedButtonFXML视图只创建了一个HBox,它的左右两侧分别有两个锚烷和一个标签和按钮。单击按钮时,它调用SpecializedButton控制器类中的doSomething()


问题

在这个设置中,我使用FXML将视图与应用程序逻辑分离

但是,如果我想创建一个扩展SpecializedButton的新HighlySpecializedButton类,我也不知道如何“扩展”视图

如果我想使用SpecializedButton视图,但为HighlySpecializedButton修改它,我必须将视图代码复制到一个新的FXML文件中,从而产生重复的代码,而不是正确的继承

如果我没有使用FXML,而是在Java类中创建GUI组件,那么扩展该类将使我能够正确继承和添加/修改超类中的组件

我显然误解了JavaFX的一些非常重要的概念


问题

在这种情况下,FXML视图是否如此“愚蠢”,以至于每次我想从自定义组件继承时都必须创建一个全新的FXML视图

或者,如果我误解了真正的问题,那么创建可扩展自定义JavaFX组件的正确方法是什么,有没有FXML


我非常感谢您的任何见解。提前谢谢

我以前没有这样做过,但是您可以在实例化新的自定义组件时实现初始化接口来设置视图组件

要添加新组件(标签、按钮、img等),我会将视图文件中的所有子组件包装在AnchorPane、GridPane、VBox或您希望以编程方式添加更多组件的视图文件中。既然您正在从HBox扩展您的类,那么您已经可以这样做了

下面是我要做的:

public class SpecializedButton extends HBox implements Initializable{

@FXML private Button button;
@FXML private Label label;

public SpecializedButton(){
    FXMLLoader loader = new FXMLLoader( getClass().getResource( "SpecializedButton.fxml" ) );

    loader.setRoot( this );
    loader.setController( this );

    try {
        loader.load();
    } catch ( IOException e ) {
        throw new RuntimeException( e );
    }
}

// specialized methods for this specialized button
// ...
public void doSomething() {
    button.setText( "Did something!" );
}

@Override
public void initialize(URL url, ResourceBundle rb) {
    button.setText("Initialized Text");
}  
}
所以对于HighlySpecializedButton类:

public class HighlySpecializedButton extends SpecializedButton {



public HighlySpecializedButton (){
    super();
}

// HighlySpecializedButton methods


@Override
public void initialize(URL url, ResourceBundle rb) {
    this.getChildren().add(new Button("New Button"));

}  
}

希望这能帮助您

据我所知,您希望能够扩展现有组件并避免 复制并粘贴新组件的整个标记

可以使用
@DefaultProperty
注释为组件定义扩展点。 看看e.x.
javafx.scene.layout.Pane
:有一个
可观察列表getChildren()
使用
@DefaultProperty(“子项”)
定义。 这样,当您使用e.x a
HBox
(扩展窗格)作为组件的根元素时,所有子组件都会添加到由窗格定义的
子属性中

同样,您可以在FXML中定义扩展点:

SpecializedButton.fxml(在本例中,我将其简化了一点)

SuperSpecializedButton.fxml

<fx:root type="SpecializedButton">
  <Label text="EXTENDED HALLO"/>
</fx:root>
如您所见,我只需要为超级专用组件定义fxml

。在此之前,超类的组件注入无法与FXMLLoader一起工作


我在GITHUB:

中添加了一个工作示例:这看起来像是对继承的过度使用:考虑使用聚合来代替。但是,要按你想要的方式去做,你就不能用一个?或者,让“子类组件”的
FXML
引用a
。其他问题:您是否扩展过html文档?FXML是一种可编写脚本、基于XML的标记语言,用于构建Java对象图。这是这里的文档:他要求FXML继承,而不是在java代码中进行继承。@NwDx他还问“创建可扩展自定义JavaFX组件的正确方法是什么,使用或不使用FXML?”
public class SpecializedButton extends HBox implements Initializable{

@FXML private Button button;
@FXML private Label label;

public SpecializedButton(){
    FXMLLoader loader = new FXMLLoader( getClass().getResource( "SpecializedButton.fxml" ) );

    loader.setRoot( this );
    loader.setController( this );

    try {
        loader.load();
    } catch ( IOException e ) {
        throw new RuntimeException( e );
    }
}

// specialized methods for this specialized button
// ...
public void doSomething() {
    button.setText( "Did something!" );
}

@Override
public void initialize(URL url, ResourceBundle rb) {
    button.setText("Initialized Text");
}  
}
public class HighlySpecializedButton extends SpecializedButton {



public HighlySpecializedButton (){
    super();
}

// HighlySpecializedButton methods


@Override
public void initialize(URL url, ResourceBundle rb) {
    this.getChildren().add(new Button("New Button"));

}  
}
<fx:root type="HBox">
  <HBox>
    <Label fx:id="label" text="Click to do something: " />
    <HBox fx:id="extension"></HBox>
  </HBox>

  <HBox>
    <Button fx:id="button" onAction="#doSomething"/>
  </HBox>
</fx:root>
@DefaultProperty(value = "extension")
public class SpecializedButton extends HBox
{
    @FXML private HBox extension;

    public ObservableList<Node> getExtension() {
        return extension.getChildren();
    }
    // ... more component specific code
}
<fx:root type="SpecializedButton">
  <Label text="EXTENDED HALLO"/>
</fx:root>
public class SuperSpecializedButton extends SpecializedButton
{
    // ... more component specific code
}