我必须在哪里初始化类成员变量JavaFX

我必须在哪里初始化类成员变量JavaFX,java,javafx,scenebuilder,Java,Javafx,Scenebuilder,我正在通过Java中的scene builder使用JavaFX和JFoenix制作一个应用程序,但是我在初始化类成员变量时遇到了一些问题。这是我的密码 public class MessageApp extends Application { private AnchorPane mainLayout; private Stage primaryStage; private int i = 5; public void init() { i

我正在通过Java中的scene builder使用JavaFX和JFoenix制作一个应用程序,但是我在初始化类成员变量时遇到了一些问题。这是我的密码

public class MessageApp extends Application {

    private AnchorPane mainLayout;
    private Stage primaryStage;
    private int i = 5;

    public void init() {
        i = 0;
    }

    public void start(Stage primaryStage) {
        try {
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(PeerApp.class.getResource("PeerApp.fxml"));
            mainLayout = loader.load();
        } catch (IOException e) {
            e.printStackTrace();
        }

        this.primaryStage = primaryStage;
        this.primaryStage.setTitle("Test");
        JFXDecorator decorator = new JFXDecorator(primaryStage, mainLayout);
        decorator.setCustomMaximize(true);
        Scene scene = new Scene(decorator, 600, 400);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    @FXML
    private void clickSendMessage() {
        System.out.println("i = " + i);
    }

    public static void main(String[] args) {
        launch(args);
    }
}
这里的问题是,当我单击触发
clickSendMessage
功能的发送按钮时,即使我在
init
功能或
start
功能中将I重置为0,我的
println
打印“I=5”。重置它的唯一方法是将i=0放入clickSendMessage函数本身

因此,在这种情况下,这不是一个大问题,但是如果我在声明过程中没有初始化类成员变量,即使我在
init
start
函数中初始化它,当我单击我的发送按钮时,我的应用程序崩溃,因为在这个阶段它仍然被视为null,但我不知道为什么

有什么线索吗?我必须在哪里初始化我的类成员变量

编辑:

好的,我试着为我的视图创建一个专用的控制器,我的第一个问题似乎已经解决了,一切都按照预期进行了初始化,但是现在我的
列表视图
没有在每次我向列表中添加
联系人
时更新,但以前是这样。我不知道我通过创建一个独立的控制器打破了什么,知道吗

这是完整的代码

PeerApp.java

public class PeerApp extends Application {

    private AnchorPane mainLayout;
    private Stage primaryStage;

    public void start(Stage primaryStage) {
        try {
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(PeerApp.class.getResource("PeerApp.fxml"));
            mainLayout = loader.load();
        } catch (IOException e) {
            e.printStackTrace();
        }

        this.primaryStage = primaryStage;
        this.primaryStage.setTitle("Peer Messenger");
        JFXDecorator decorator = new JFXDecorator(primaryStage, mainLayout);
        decorator.setCustomMaximize(true);
        Scene scene = new Scene(decorator, 600, 400);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
PeerAppController.java

public class PeerAppController {

    private PeerApplication peer = new PeerApplication("1234");
    private ObservableList<Contact> contacts;
    private ChangeListener<Contact> listener;
    private int i = 5;

    @FXML
    private JFXListView<Contact> contactList;
    @FXML
    private JFXButton addContactButton;
    @FXML
    private JFXTextArea messageTextArea;
    @FXML
    private GridPane chatGridPane;
    @FXML
    private JFXButton sendButton;

    @FXML
    public void initialize() {
        initPeer();
        initRootLayout();
        contacts = FXCollections.observableArrayList(Contact.extractor());

        contactList.setItems(contacts);

        listener = new ChangeListener<Contact>() {
            @Override
            public void changed(ObservableValue<? extends Contact> observable, Contact oldValue, Contact newValue) {
                chatGridPane.getChildren().clear();
                List<Message> conversation = contacts.get(contactList.getSelectionModel().getSelectedIndex()).getConversation();
                int i;

                i = 0;
                while (conversation.size() >= i + 1) {
                    Label messageLabel = new Label(conversation.get(i).getContent());
                    chatGridPane.addRow(i, messageLabel);
                    i++;
                }
            }
        };
        contactList.getSelectionModel().selectedItemProperty().addListener(listener);

        i = 0;
    }

    private void initPeer() {
        peer.init(EncryptionType.NONE, CompressionType.NONE);
        peer.getPeerDaemonPlug().setComListener(new ICommunicationListener() {
            @Override
            public void onDataReceived(String s) {
                Label labelMessage = new Label(s);
                GridPane.setHalignment(labelMessage, HPos.RIGHT);
                chatGridPane.addRow(getRowCount(chatGridPane) + 1, labelMessage);
                contacts.get(contactList.getSelectionModel().getSelectedIndex()).getConversation().add(new Message(s, false));
            }

            @Override
            public void onStreamPacketCompleted(OutputStream outputStream) {
            }
        });
    }

    private void initRootLayout() {
        // Init the layout
        ColumnConstraints c1 = new ColumnConstraints();
        c1.setPercentWidth(100);

        sendButton = new JFXButton();
        contactList = new JFXListView<Contact>();
        chatGridPane = new GridPane();
        chatGridPane.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        chatGridPane.getColumnConstraints().add(c1);
    }

    @FXML
    private void clickAddContact() {
        TextInputDialog dialog = new TextInputDialog("");
        dialog.setTitle("New Contact");
        dialog.setHeaderText("Add a new contact");
        dialog.setContentText("Enter the ID of your contact:");

        Optional<String> result = dialog.showAndWait();
        result.ifPresent(id -> {
            Contact c = new Contact(id);
            contacts.add(c);
            System.out.println(contactList.getItems().size());
        });
    }

    @FXML
    private void clickSendMessage() {
        // Not to be there

        String message = messageTextArea.getText();
        Label labelMessage = new Label(message);

        try {
            peer.sendRequest(sendDataToNode, new SendDataToNodeParam(contactList.getSelectionModel().getSelectedItem().toString(), message));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            i = 0;
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            i = 1;
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            i = 2;
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            i = 3;
            e.printStackTrace();
        } catch (BadPaddingException e) {
            i = 4;
            e.printStackTrace();
        } catch (IOException e) {
            i = 5;
            e.printStackTrace();
        }

        messageTextArea.setText("");
        GridPane.setHalignment(labelMessage, HPos.LEFT);
        chatGridPane.addRow(getRowCount(chatGridPane) + 1, labelMessage);
        contacts.get(contactList.getSelectionModel().getSelectedIndex()).getConversation().add(new Message(message, true));
        System.out.println("i = " + i);
    }

    private int getRowCount(GridPane pane) {
        int numRows = pane.getRowConstraints().size();
        for (int i = 0; i < pane.getChildren().size(); i++) {
            Node child = pane.getChildren().get(i);
            if (child.isManaged()) {
                Integer rowIndex = GridPane.getRowIndex(child);
                if(rowIndex != null){
                    numRows = Math.max(numRows,rowIndex+1);
                }
            }
        }
        return numRows;
    }

}
公共类PeerAppController{
私有PeerApplication对等方=新PeerApplication(“1234”);
私人关系;
私人监听;
私人int i=5;
@FXML
私有JFXListView联系人列表;
@FXML
专用JFXButton addContactButton;
@FXML
私有JFXTextArea messageTextArea;
@FXML
私有网格窗格聊天网格窗格;
@FXML
私有JFXButton sendButton;
@FXML
公共无效初始化(){
initPeer();
initRootLayout();
contacts=FXCollections.observearraylist(Contact.extractor());
联系人列表。设置项目(联系人);
listener=新的ChangeListener(){
@凌驾

public void已更改(observeValue我的朋友,你是否也将PeerApp.fxml的控制器设置为MessageApp

否则,当您单击“发送”按钮时,它不会触发clickSendMessage()

但如果您将PeerApp.fxml的控制器设置为MessageApp,javafx会自动创建MessageApp的另一个实例,因此如果您单击“发送”按钮,它实际上会触发MessageApp的clickSendMessage()的另一个实例,并打印其i变量

或者您可以发布您的PeerApp.fxml代码以方便我们检查


init()方法是从应用程序类重写的,它将在我们启动javafx应用程序时自动运行。

我的朋友,您是否也将PeerApp.fxml的控制器设置为MessageApp

否则,当您单击“发送”按钮时,它不会触发clickSendMessage()

但如果您将PeerApp.fxml的控制器设置为MessageApp,javafx会自动创建MessageApp的另一个实例,因此如果您单击“发送”按钮,它实际上会触发MessageApp的clickSendMessage()的另一个实例,并打印其i变量

或者您可以发布您的PeerApp.fxml代码以方便我们检查


init()方法是从应用程序类重写的,它将在我们启动javafx应用程序时自动运行。

在我看来,将负责启动应用程序并加载
.fxml
文件的类混合在一起是不好的做法对于作为您的
控制器的类
,它关心控制您的UI,例如,在您的示例中,您有
clickSendMessage()
方法,该方法必须在控制器类中

因此,我建议您编写一个单独的类作为控制器,将控制器附加到
.fxml
文件,然后您可以更轻松地处理UI和逻辑部分之间的所有交互。我可以向您展示一个简单的示例:

package stackoverflow;

import javafx.fxml.Initializable;

import java.net.URL;
import java.util.ResourceBundle;

public class TestController implements Initializable {

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // here are  all stuffs initialized
    }
}
然后
.fxml
文件如下所示:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="500.0" prefWidth="700.0" xmlns="http://javafx.com/javafx/8.0.91" xmlns:fx="http://javafx.com/fxml/1" 
fx:controller="stackoverflow.TestController">
// here you can fill it with content
</AnchorPane>

//在这里,您可以用内容填充它
现在你有了一个单独的控制器和一个
.fxml
,你可以像在主类中那样加载这个
.fxml
,然后你可以在你的控制器中添加所有你想要控制你的应用程序的东西,包括这个方法。这是一个构建javafx应用程序的简单而清晰的方法。
我认为这是可以理解的,但如果我错过了什么,请随时问我。

在我看来,混合负责启动应用程序并加载
.fxml
文件的类是一种不好的做法对于作为您的
控制器的类
,它关心控制您的UI,例如,在您的示例中,您有
clickSendMessage()
方法,该方法必须在控制器类中

因此,我建议您编写一个单独的类作为控制器,将控制器附加到
.fxml
文件,然后您可以更轻松地处理UI和逻辑部分之间的所有交互。我可以向您展示一个简单的示例:

package stackoverflow;

import javafx.fxml.Initializable;

import java.net.URL;
import java.util.ResourceBundle;

public class TestController implements Initializable {

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // here are  all stuffs initialized
    }
}
然后
.fxml
文件如下所示:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="500.0" prefWidth="700.0" xmlns="http://javafx.com/javafx/8.0.91" xmlns:fx="http://javafx.com/fxml/1" 
fx:controller="stackoverflow.TestController">
// here you can fill it with content
</AnchorPane>

//在这里,您可以用内容填充它
现在你有了一个单独的控制器和一个
.fxml
,你可以像在主类中那样加载这个
.fxml
,然后你可以在你的控制器中添加所有你想要控制你的应用程序的东西,包括这个方法。这是一个构建javafx应用程序的简单而清晰的方法。
我认为这是可以理解的,但如果我错过了什么,请随时问我。

如果你不初始化变量,它们有一个默认值。对于任何
对象
s,它是
null
,对于
int
它是0。并且你从不调用
init()
那么为什么假设i为0?我如何在声明时直接初始化尽可能多的字段。如果您希望
i
为0,则将其声明为
private int i=0<