在JavaFXActionEvent中调用方法
我是JavaFX新手,我想创建一个视图类,当按下按钮触发事件时,该类将调用控制器中的方法。我的代码如下:在JavaFXActionEvent中调用方法,java,javafx,actionevent,Java,Javafx,Actionevent,我是JavaFX新手,我想创建一个视图类,当按下按钮触发事件时,该类将调用控制器中的方法。我的代码如下: 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.Act
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的尸体
场景生成器
,其中提供了拖放功能,您可以在几秒钟内设计屏幕。在代码部分中,您只需声明方法名称并在代码处理程序类中实现该方法
您可以从获得它,因为您有两个构造函数。我猜您正在某处加载一个FXML,它将使用no-args构造函数实例化您的控制器。在这种情况下,menuCtrl未初始化
如果要在FXML中实例化menuCtrl,请在字段中添加@FXML注释。您的设置是不寻常的,因为您的控制器类(称为
MenuView
)是调用(通过窗口类间接调用)FXMLLoader加载方法的类。fxmloader
解析FXML,查看fx:controller
属性,然后使用默认(无参数)构造函数实例化它。(我在此假设您没有在窗口中的fxmloader
上调用setController
或setControllerFactory
),因此您有两个控制器实例:一个是创建加载程序的实例(initialize()方法不会被调用,@FXML
-注释字段也不会被注入),并且由fxmloader
创建的字段(它调用了无参数构造函数,因此该实例的窗口和menuCtrl
字段不会被初始化)
您应该重构它,以便创建FXMLLoader并将其传递给窗口类以便在其他地方加载(即,不实例化控制器),或者应该在FXMLLoader上显式设置控制器。您可以通过两个步骤实现后者:
从main menu.fxml中删除fx:controller
属性
将控制器显式设置为已在renderMainMenu
方法中创建的实例:
--
这个类是它加载的同一个FXML的控制器类吗?(即main menu.fxml是否在根元素中有fx:controller=“MenuView”
)这将是一个不寻常的设置,至少在这里是这样。是的,main menu.fxml中的fx:controller是MenuView。为什么这么奇怪?因为您必须创建控制器的一个实例才能加载FXML,然后FXML将创建控制器的另一个实例。通常,您会从不同的类加载FXML(例外可能是如果您使用的是(看起来非常不同)。啊,这是有道理的。我稍后会尝试。先生,您真是太棒了。我对FX的体系结构是如何工作的有一个完全错误的想法,这就彻底解决了问题。
FXMLLoader loader = new FXMLLoader((getClass().getResource("MainMenu.fxml"))) ;
loader.setController(this);
window.loadFXML(loader);