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(它包含一個抽象類別 canmessage
和 pctovcumessage
擴充它):
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("222")
替換為
new PcToVcuMessage("222", Integer.parseInt(inDesiredVelocity.getText()))
然后只需从 canmessage
类中删除 extends mainviewcontroller
即可。这显然完全没有意义(消息不是控制 ui 的东西)。
一些与您的代码无关的问题:
canmessage
是一个动词(或动词短语)。可能 message
更合适,但我还是不太明白你在这里建模的内容。以上是如何正確繼承 FXML 帶註解的屬性以使其在子類別中可用?的詳細內容。更多資訊請關注PHP中文網其他相關文章!