首頁  >  文章  >  如何正確繼承 FXML 帶註解的屬性以使其在子類別中可用?

如何正確繼承 FXML 帶註解的屬性以使其在子類別中可用?

WBOY
WBOY轉載
2024-02-22 13:46:14713瀏覽

php小編小新為您帶來本期的Java問答:如何正確繼承FXML帶註解的屬性以使其在子類別中可用?在Java開發中,正確繼承FXML帶註解的屬性是常見問題,也是開發過程中需要注意的地方。下面我們將詳細討論如何正確繼承帶註釋的屬性,使其在子類別中可用,以幫助您更好地解決此問題。

問題內容

問題

#我正在嘗試透過控制器區域網路實現訊息傳輸,其中訊息是透過使用 javafx 創建的 gui 根據用戶輸入構建的。

我有一個連結到 main.fxml 的 maincontroller 類別。在 maincontroller 中,我定義了一個帶有 fxml 註解的 textfield 屬性 in_desiredvelocity,該屬性正確連結到 main.fxml 中的 fx:id

然後我定義了一個抽象類別 canmessage,它定義了必須透過網路傳送的訊息的主幹。

現在類別 pctovcumessage 實作了特定類型的 canmessage。為了能夠存取fxml 屬性(在maincontroller 中定義),我決定抽象類別canmessage 擴充功能maincontroller,而pctovcumessage 擴充功能 canmessage

應用程式編譯正確,但當我在 gui 中輸入時,將啟動 textfield in_desiredvelocity nullpointerexception

問題

儘管上述fxml 屬性是由pctovcumessage 繼承的(它繼承自抽象類別canmessage 並且擴展了maincontroller),但我如何在此類中使用它來實現我的目標?

主要

package canbusgui;

import javafx.application.application;
import javafx.fxml.fxmlloader;
import javafx.scene.scene;
import javafx.stage.stage;

import java.io.ioexception;

public class mainapplication extends application {
    public static stage stage = null;

    @override
    public void start(stage stage) throws ioexception {
        
        stage.setoncloserequest(event -> {
           system.exit(0);
        });

        mainapplication.stage = stage;

        // create a fxmlloader to load the fxml file that defines the user interface
        fxmlloader fxmlloader = new fxmlloader(mainapplication.class.getresource("mainview.fxml"));

        scene scene = new scene(fxmlloader.load());

        stage.settitle("canbus gui");
        stage.setscene(scene);
        stage.setresizable(false);
        stage.setminheight(768);
        stage.setminwidth(1366);
        stage.show();
    }

    public static void main(string[] args) {
        launch();
    }
}

主控制器

package canbusgui;

import javafx.application.platform;
import javafx.collections.fxcollections;
import javafx.fxml.fxml;
import javafx.scene.input.keycode;
import javafx.scene.input.keyevent;


public class mainviewcontroller {
  @fxml
  protected textfield in_desiredvelocity;

  @fxml
  public void initialize (){

        in_desiredvelocity.addeventfilter(keyevent.key_pressed, event -> {
                if (event.getcode() == keycode.enter) {
                    try {
                        sendmessage(new pctovcumessage("222"));
                    }
                    catch (exception e) {
                        throw new runtimeexception(e);
                    }
                }
        });
  }
  

  public void sendmessage(canmessage message) throws exception {
        
        message.constructdata();
       
        message.validateinputs();
        
        byte[] data = message.getdata();

        // send the data array to the can bus
        canbuscontroller.sendcommand(hexformat.fromhexdigits(message.getid()), data);
  }

}

canmessage.java(它包含一個抽象類別 canmessagepctovcumessage 擴充它):

package canbusgui;

import static java.lang.Integer.parseInt;

public abstract class canMessage extends MainViewController{

    // Declare common attributes
    protected String id;
    protected byte[] data;

    public canMessage(String id) {
        this.id = id;
        // Initialize an empty byte array for data
        this.data = new byte[8];
    }


    // Define an abstract method to construct the data array
    public abstract void constructData();

    // Define an abstract method to validate the inputs
    public abstract void validateInputs() throws Exception;

    // Define a getter method for the data array
    public byte[] getData() {
        return this.data;
    }

    public String getId() {
        return this.id;
    }

}


// Define a subclass for PC_to_VCUMessage message
class PcToVcuMessage extends canMessage {


    public PcToVcuMessage(String id) {
        // Call the superclass constructor
        super(id);
    }


    // Override the constructData method
    @Override
    public void constructData() {


        data[0] = (byte) 0;
        data[1] = (byte) 0;
        data[2] = (byte) 0;
        data[3] = (byte) parseInt(in_desiredVelocity.getText()); //HERE in_desiredVelocity is null and a NillPointerException is launched
        data[4] = (byte) 0;
        data[5] = (byte) 0;
        data[6] = (byte) 0;
        data[7] = (byte) 0;
    }

    public  void validateInputs() throws Exception{}


}

編輯

can 封包的格式如下:id(hex), data0, data1, data2, data3, ......, data7。因此,當我在控制器中呼叫 pcutovcumessage 的建構子時,我傳遞訊息 222 的 id(順便說一句,該 id 在裝置的資料表中指定)

pcutovcumessage 中,我需要存取fxml 屬性in_desiredvelocity,該屬性已由用戶透過在gui 的textfield 中鍵入值來設定:透過這種方式,可以檢索用戶鍵入的值以建構訊息。

編輯2

由於可以有多個具有不同id的訊息,所以我想到了在控制器中的sendmessage方法中使用多態性。此外,可能存在需要從控制器類別存取多個 fxml 屬性的訊息。

解決方法

這根本不是繼承的作用。繼承是類別之間的關係,而不是物件之間的關係。

當你這樣做時

public class mainviewcontroller {
    // ...
    protected textfield indesiredvelocity;
    // ...
}

這意味著 mainviewcontroller 的每個實例都會有一個名為 indesiredvelocity 的字段,其類型為 textfield

當你這樣做時

public abstract class canmessage extends mainviewcontroller {
    // ...
}

這表示 canmessage 的每個實例也是 mainviewcontroller 的實例。

載入fxml 時,fxmlloader 會建立mainviewcontroller 的實例(因為fxml 中有fx:controller="canbusgui.mainviewcontroller"),並在該實例中初始化indesiredvelocity 欄位對fxml 中宣告的文字欄位的參考。

稍後在你的控制器中,你會這樣做

new pctovcumessage("222")

當然,這會創建一個新的 pctovcumessage 實例,其 id 為 "222"。由於pctovcumessage 繼承自canmessage,因此該新實例也是canmessage 的實例,並且由於canmessage 繼承自mainviewcontroller,因此該實例也是mainviewcontrollerzqbendczq 的實例b,由於<code>mainviewcontroller 的每個實例都有一個字段indesiredvelocity,因此pctovcumessage 的這個新實例有一個名為indesiredvelocity 的字段,類型為textfield

但是,您永遠不會初始化該欄位(並且沒有明智的方法可以這樣做),因此 pctovcumessage 中的 indesiredvelocity 欄位為 null。

這樣做沒有任何意義。我真的不明白你的域模型是什麼(我可能不需要回答這個問題),但是對於 textfield 作為類型為某種消息的對象的一部分沒有任何意義.

相反,將此訊息發送的資料作為 pctovcumessage 的一部分可能是有意義的。 ie。你可以做

class pctovcumessage extends canmessage {

    private int desiredvelocity ;


    public pctovcumessage(string id, int desiredvelocity) {
        // call the superclass constructor
        super(id);
        this.desiredvelocity = desiredvelocity;
    }


    // override the constructdata method
    @override
    public void constructdata() {


        data[0] = (byte) 0;
        data[1] = (byte) 0;
        data[2] = (byte) 0;
        data[3] = (byte) desiredvelocity;
        data[4] = (byte) 0;
        data[5] = (byte) 0;
        data[6] = (byte) 0;
        data[7] = (byte) 0;
    }

    public  void validateinputs() throws exception{}


}

並在控制器中將 new pctovcumessage(&quot;222&quot;) 替換為

new PcToVcuMessage("222", Integer.parseInt(inDesiredVelocity.getText()))

然后只需从 canmessage 类中删除 extends mainviewcontroller 即可。这显然完全没有意义(消息不是控制 ui 的东西)。

一些与您的代码无关的问题:

  1. 不要使用文本字段注册按键处理程序。要处理用户按 enter 的操作,请以通常的方式使用操作处理程序。
  2. 适当地命名类和变量。类名称应该是名词(它们代表事物)。 canmessage 是一个动词(或动词短语)。可能 message 更合适,但我还是不太明白你在这里建模的内容。

以上是如何正確繼承 FXML 帶註解的屬性以使其在子類別中可用?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除