[英]How to extend custom JavaFX components that use FXML
如果為視圖使用FXML,如何正確擴展自定義JavaFX組件以添加或修改其GUI組件?
作為示例場景,假設我使用以下方法創建自定義JavaFX組件:
SpecializedButton.java(控制器)
package test;
import java.io.IOException;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
public class SpecializedButton extends HBox
{
@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!" );
}
}
SpecializedButton.fxml(查看)
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.control.Button?>
<fx:root type="HBox" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<AnchorPane HBox.hgrow="ALWAYS">
<children>
<Label fx:id="label" text="Click to do something: " AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane HBox.hgrow="ALWAYS">
<children>
<Button fx:id="button" onAction="#doSomething" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</children>
</fx:root>
MyApp.java
package test;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class MyApp extends Application
{
public static void main( String[] args )
{
launch( args );
}
public void start( Stage stage ) throws Exception
{
stage.setScene( new Scene( new SpecializedButton(), 300, 50 ) );
stage.show();
}
}
SpecializedButton類加載FXML視圖(SpecializedButton.fxml)並充當它的控制器。
SpecializedButton FXML視圖分別在左側和右側創建一個帶有兩個AnchorPanes和一個Label和Button的HBox。 單擊該按鈕時,它會調用SpecializedButton控制器類中的doSomething()。
問題
通過此設置,我使用FXML將視圖與應用程序邏輯分開。
但是,如果我想創建一個擴展SpecializedButton的新的HighlySpecializedButton類,我不知道如何“擴展”視圖。
如果我想使用SpecializedButton視圖,但是為HighlySpecializedButton修改它,我必須將視圖代碼復制到新的FXML文件中,導致重復的代碼而不是正確的繼承。
如果我沒有使用FXML,而是在Java類中創建GUI組件,那么擴展該類將使我能夠正確地繼承和添加/修改超類中的組件。
我顯然誤解了一些關於JavaFX的非常重要的概念。
題
在這種情況下,FXML視圖是如此“愚蠢”,每當我想從自定義組件繼承時,我必須創建一個全新的FXML視圖嗎?
或者,如果我誤解了真正的問題,那么使用或不使用FXML創建可擴展自定義JavaFX組件的正確方法是什么?
我非常感謝任何見解。 提前致謝!
根據我的理解,您希望能夠擴展現有組件並避免復制和粘貼新組件的整個標記。
您可以使用@DefaultProperty
注釋為組件定義擴展點。 查看ex javafx.scene.layout.Pane
:使用@DefaultProperty("children")
定義了一個ObservableList getChildren()
@DefaultProperty("children")
。 這樣,當您使用ex HBox
(擴展Pane)作為組件的根元素時,所有子組件都將添加到Pane定義的children
屬性中。
以同樣的方式,您可以在FXML中定義擴展點:
SpecializedButton.fxml (我為這個例子簡化了一點)
<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>
HBox fx:id="extension"
將是我的擴展點:
@DefaultProperty(value = "extension")
public class SpecializedButton extends HBox
{
@FXML private HBox extension;
public ObservableList<Node> getExtension() {
return extension.getChildren();
}
// ... more component specific code
}
SuperSpecializedButton.fxml
<fx:root type="SpecializedButton">
<Label text="EXTENDED HALLO"/>
</fx:root>
和:
public class SuperSpecializedButton extends SpecializedButton
{
// ... more component specific code
}
如您所見,我只需要為超專用組件定義fxml。
此代碼僅適用於JavaFX> = 2.1 。 事先,超類的組件注入不適用於FXMLLoader。
我在github上添加了一個工作示例: https : //github.com/matrak/javafx-extend-fxml
我之前沒有這樣做過,但是當您實例化一個新的自定義組件時,您可以實現Initializable接口來設置視圖組件。
要添加新組件(標簽,按鈕,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"));
}
}
希望這可以幫到你
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.