在Java Fx ActionEvent中调用方法

时间:2014-10-03 03:38:54

标签: java javafx actionevent

我是JavaFX的新手,我想创建一个视图类,当按钮按下触发事件时,该视图类将调用Controller中的方法。我的代码如下:

package spacetrader.menu;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.layout.Pane;
import spacetrader.Window;

public class MenuView implements Initializable {
    public Window window;
    public MenuCtrl menuCtrl;

    @FXML
    Button start;
    @FXML
    Pane background;
    @FXML
    Button exit;

    public MenuView() {};

    public MenuView(Window aWindow, MenuCtrl aMenuCtrl) {
        window = aWindow;
        menuCtrl = aMenuCtrl;
    }

    void renderMainMenu() {
        try {
            window.loadFXML(new FXMLLoader((getClass().getResource("MainMenu.fxml"))));
        } catch (IOException ex) {
            Logger.getLogger(MenuView.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        start.setOnAction((ActionEvent event) -> menuCtrl.newGame());
        exit.setOnAction((ActionEvent event) -> menuCtrl.closeApplication());
    }
}

这个编译,但是当我运行它并按下按钮时,我在lambda表达式上得到一个空指针异常。例外是指“menuCtrl”。我该如何设置我的程序来调用menuCtrl.newGame()按钮?

以下是我已经尝试过的内容:

  • 我已将setOnAction命令移到各种方法之间。
  • 用System.out.prinln语句替换了对menuCtrl方法的调用,以确认这是有效的。它确实。
  • 我已经用System.out.println(this)替换了menuCtrl方法,以确保没有范围问题。它按预期打印“spacetrader.menu.MenuView@74f51979”。
  • 将Lambda表达式转换为匿名内部类
  • 使用块作为lambda的主体

3 个答案:

答案 0 :(得分:1)

您的设置不常见,因为您的控制器类(您称之为MenuView)是调用(间接地,通过您的Window类)FXMLLoader' s的类加载方法。 FXMLLoader解析FXML,查看fx:controller属性,然后使用默认(无参数)构造函数对其进行实例化。 (我在这里假设您不能在setController中的setControllerFactory上致电FXMLLoaderWindow.loadFXML。)因此,您有两个控制器实例:一个它创建了加载器(从不调用initialize()方法,并且永远不会注入@FXML - 带注释的字段),以及由FXMLLoader创建的加载器(称为无参数构造函数) ,因此未为该实例初始化windowmenuCtrl字段。)

你应该重构这个,以便创建FXMLLoader并传递给Window类以便在其他地方加载(即不实例化控制器),或者你应该在FXMLLoader上明确设置控制器。您可以通过两个步骤实现后者:

  1. 从MainMenu.fxml
  2. 中删除fx:controller属性
  3. 将控制器显式设置为已在renderMainMenu方法中创建的实例:
  4. -

    FXMLLoader loader = new FXMLLoader((getClass().getResource("MainMenu.fxml"))) ;
    loader.setController(this);
    window.loadFXML(loader);
    

答案 1 :(得分:0)

您可以尝试使用拖放功能的Scene Builder,您可以在几秒钟内设计一个屏幕。在代码部分中,您只需声明方法名称并在代码处理程序类中实现该方法。

您可以从here

获取

答案 2 :(得分:0)

你有两个构造函数。我的猜测是你在某处加载一个FXML,它将使用no-args构造函数实例化你的控制器。在这种情况下,menuCtrl未初始化。

如果您在FXML中实例化menuCtrl,则在该字段中添加@FXML注释。