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

时间:2017-06-21 08:57:22

标签: java javafx scenebuilder

我通过Java中的场景构建器使用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);
    }
}

这里的问题是,即使我在init函数或start函数中将I重置为0,当我点击触发clickSendMessage函数的发送按钮时,我{ {1}}打印" i = 5"。重置它的唯一方法是在clickSendMessage函数本身中放置i = 0.

因此,在这种情况下,这不是一个大问题,但如果我在声明过程中没有初始化类成员变量,即使我在println或{{1}中初始化它也是如此。我点击发送按钮时,我的应用程序崩溃了,因为在这个阶段它仍然被视为空,但我不知道为什么。

为什么有任何线索?我在哪里初始化我的类成员变量?

编辑:

好的,所以我尝试为我的视图创建一个专用控制器,我的第一个问题似乎已修复,所有内容都按预期初始化,但现在每次添加{{1}时我的init都不会更新我的名单,但以前的情况。通过创建一个独立的控制器,我不知道我打破了什么?任何想法?

这里是完整的代码

PeerApp.java

start

PeerAppController.java

ListView

Contact.java

Contact

PeerApp.fxml

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

2 个答案:

答案 0 :(得分:3)

在我看来,将责任与启动您的应用程序的类混合并将.fxml文件加载到您的Controller类,关注控制您的类是不好的做法。用户界面,例如在您的情况下,您必须拥有必须位于控制器类中的clickSendMessage()方法。

所以我建议您编写一个单独的类作为您的Controller,将控制器附加到.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应用程序的简单明了的方法。 我认为这是可以理解的,但如果我错过了什么,请随时问我。

答案 1 :(得分:1)

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

如果没有,当你点击发送按钮时,它不会触发clickSendMessage()。

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

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

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