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中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号