【问题标题】:JavaFX button binding exceptionJavaFX 按钮绑定异常
【发布时间】:2017-03-04 06:47:30
【问题描述】:
public class AccountOverviewController {

//declarations ...

@FXML
private Button undoButton;

@FXML
private Button redoButton;

@FXML
private void initialize() {
    transactionsTable.getSelectionModel().setSelectionMode(
            SelectionMode.MULTIPLE);

    dateColumn.setCellValueFactory(dataValue -> dataValue.getValue()
            .getDateProperty());
    payeeColumn.setCellValueFactory(dataValue -> dataValue.getValue()
            .getPayeeProperty());
    categoryColumn.setCellValueFactory(dataValue -> dataValue.getValue()
            .getCategoryProperty());
    inflowColumn.setCellValueFactory(dataValue -> dataValue.getValue()
            .getInflowProperty());

    deleteButton.disableProperty().bind(Bindings.isEmpty(transactionsTable.getSelectionModel().getSelectedItems()));

    editButton.disableProperty().bind(Bindings.size(transactionsTable.getSelectionModel().getSelectedItems()).isNotEqualTo(1));

    undoButton.disableProperty().bind(Bindings.isEmpty(commandRegistry.getCommandStack()));
    redoButton.disableProperty().bind(Bindings.isEmpty(commandRegistry.getUndoCommandStack()));
}

//handlers&setters ...
}

最后的这两行导致错误。当命令堆栈为空时,我想禁用按钮。我不知道为什么。例如,为删除/编辑按钮禁用相同的按钮可以正常工作。没有这两个的整个应用程序都可以正常工作。

异常链:

javafx.fxml.LoadException: 
/home/simon/eclipse/java-neon-workspace/to2/lab2/cw3/bin/pl/edu/agh/iisg/to/javafx/cw3/view/AccountOverviewPane.fxml

    at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2601)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2571)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2409)
    at pl.edu.agh.iisg.to.javafx.cw3.presenter.AccountPresenter.initRootLayout(AccountPresenter.java:35)
    at pl.edu.agh.iisg.to.javafx.cw3.Main.start(Main.java:20)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$106(LauncherImpl.java:863)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$119(PlatformImpl.java:326)
    at com.sun.javafx.application.PlatformImpl.lambda$null$117(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$118(PlatformImpl.java:294)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
    at com.sun.glass.ui.gtk.GtkApplication.lambda$null$450(GtkApplication.java:139)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2566)
    ... 13 more
Caused by: java.lang.NullPointerException
    at pl.edu.agh.iisg.to.javafx.cw3.view.AccountOverviewController.initialize(AccountOverviewController.java:97)
    ... 23 more

两个堆栈在CommandRegistry 类中都是这样声明的

private ObservableList<Command> commandStack = FXCollections.observableArrayList();

吸气剂自然而然地返回自己。这里可能出了什么问题?

【问题讨论】:

  • 能否请您添加AccountOverviewController 的完整代码?您的跟踪显示 NullPointerException,您确定 commandRegistry 已初始化吗?
  • 那么第 97 行是哪一行?
  • 在这个特定的例子中,undoButoon.disablePrope... 就是这样。但是他们每个人都会导致相同的异常链。这里是整个project,这里是AccountOverviewController
  • 所以大概undoButton 为空?
  • 您似乎在访问commandRegistry 时没有对其进行初始化。

标签: user-interface button javafx binding


【解决方案1】:

查看您的project,尤其是AccountOverviewControllerAccountPresenter 之后,我会说您得到了NullPointerException,因为控制器尝试在initialize() 内访问commandRegistry 之前 该类有一个CommandRegistry 的实例。

查看AccountPresenter 的第 38 – 41 行:

AccountOverviewController controller = loader.getController();
controller.setPresenter(this);
controller.setData(DataGenerator.generateAccountData());
controller.setCommandRegistry(commandRegistry);

您创建控制器并随后设置commandRegistry。但是initialize()是在调用AccountOverviewController的构造函数后直接调用的(详情请查看this问题)。此时commandRegistry就是null

解决此问题的一种方法是将绑定移动到设置器中:

public void setCommandRegistry(CommandRegistry commandRegistry) {
    this.commandRegistry = commandRegistry;

    undoButton.disableProperty().bind(Bindings.isEmpty(commandRegistry.getCommandStack()));
    redoButton.disableProperty().bind(Bindings.isEmpty(commandRegistry.getUndoCommandStack()));

    commandLogView.setItems(commandRegistry.getCommandStack());
    commandLogView.setCellFactory(lv -> new ListCell<Command>() {
        protected void updateItem(Command item, boolean empty) {
            super.updateItem(item, empty);
            setText((item != null && !empty) ? item.getName() : null);
        };
    });
}

【讨论】:

  • 谢谢,我现在明白了。如果在调用控制器期间还没有初始化,那么绑定如何在 transactionsTable 上工作。例如editButtondeleteButton
  • @Saris 因为所有依赖项都已经存在。 editButtondeleteButton 需要 transactionTable。所有这些字段都用@FXML 注释,这是之前调用的。你只需要记住这个执行顺序:1.构造函数,2.@FXML,3.initialize()
  • 感谢您的帮助和耐心。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-17
  • 2018-01-29
  • 1970-01-01
  • 2013-10-13
相关资源
最近更新 更多