Home > Java > body text

How to properly inherit FXML annotated properties to make them available in subclasses?

WBOY
Release: 2024-02-22 13:46:14
forward
709 people have browsed it

php editor Xiaoxin brings you this issue of Java Q&A: How to correctly inherit FXML annotated properties to make them available in subclasses? In Java development, correctly inheriting FXML annotated properties is a common problem and something that needs attention during the development process. Below we will discuss in detail how to correctly inherit annotated properties and make them available in subclasses to help you better solve this problem.

Question content

Question

I'm trying to implement message transfer over a controller area network, where the messages are built based on user input through a gui created using javafx.

I have a maincontroller class linked to main.fxml. In maincontroller I have defined a textfield attribute with fxml annotation in_desiredvelocity which is properly linked to fx:id in main.fxml.

I then defined an abstract class canmessage which defines the backbone of messages that must be sent over the network.

Now class pctovcumessage implements a specific type of canmessage. To be able to access the fxml properties (defined in maincontroller) I decided that the abstract class canmessage extends maincontroller and pctovcumessage extends canmessage.

The application compiles correctly but when I type in the gui the textfield in_desiredvelocity nullpointerexception is launched.

question

Although the above fxml properties are inherited by pctovcumessage (which inherits from the abstract class canmessage and extends maincontroller), how do I add it in this class Use it to achieve my goals?

main:

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();
    }
}
Copy after login

main controller:

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);
  }

}
Copy after login

canmessage.java (it contains an abstract class canmessage and pctovcumessage extends it):

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{}


}
Copy after login

edit

The format of the can message is as follows: id(hex), data0, data1, data2, data3, ..., data7. So when I call the constructor of pcutovcumessage in the controller I pass the id of message 222 (which by the way is specified in the device's datasheet)

In pcutovcumessage I need to access the fxml property in_desiredvelocity which has been set by the user by typing the value in the textfield of the gui: In this way the user can be retrieved Value typed to build the message.

Edit 2

Since there can be multiple messages with different ids, I thought of using polymorphism in the sendmessage method in the controller. Additionally, there may be messages that require access to multiple fxml properties from the controller class.

Solution

This is not the role of inheritance at all. Inheritance is a relationship between classes, not between objects.

When you do this

public class mainviewcontroller {
    // ...
    protected textfield indesiredvelocity;
    // ...
}
Copy after login

This means that every instance of mainviewcontroller will have a field named indesiredvelocity of type textfield.

When you do this

public abstract class canmessage extends mainviewcontroller {
    // ...
}
Copy after login

This means that every instance of canmessage is also an instance of mainviewcontroller.

When loading fxml, fxmlloader will create an instance of mainviewcontroller (because there is fx:controller="canbusgui.mainviewcontroller" in fxml), and in the The indesiredvelocity field initialized in the instance is a reference to the text field declared in fxml.

Later in your controller you will do this

new pctovcumessage("222")
Copy after login

Of course, this will create a new pctovcumessage instance with the id "222". Since pctovcumessage inherits from canmessage, this new instance is also an instance of canmessage, and since canmessage inherits from mainviewcontroller, so this instance is also an instance b of mainviewcontrollerzqbendczq, since each instance of <code>mainviewcontroller has a field indesiredvelocity, so this new instance of pctovcumessage There is a field named indesiredvelocity, of type textfield.

However, you never initialize the field (and there is no sensible way to do so), so the indesiredvelocity field in pctovcumessage is null.

It makes no sense to do so. I don't really understand what your domain model is (I probably don't need to answer this question), but it doesn't make any sense for textfield to be part of an object of type some kind of message.

Instead, it might make sense to send the data with this message as part of the pctovcumessage. ie. you can do

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{}


}
Copy after login

And replace new pctovcumessage(&quot;222&quot;) in the controller with

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

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

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

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

The above is the detailed content of How to properly inherit FXML annotated properties to make them available in subclasses?. For more information, please follow other related articles on the PHP Chinese website!

source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!