java - (JavaFx)正确的方式表示静态FXML字段(以及为什么这是一个坏主意)

标签 java javafx static refactoring

我希望所有类都可以访问FXML字段。在一个完美的世界中,我会这样做:

public class CanvasController {

    @FXML
    private static final AnchorPane canvas; // This is wrong

    public static AnchorPane getCanvas() {
        return canvas;
    }
}


但是,如this similar question所述,静态字段是一个“糟糕的主意”。

我正在设计一个节点编辑器,如下所示:

enter image description here

我想从项目的任何位置添加一个node作为此AnchorPane的子级。

我想这样做是错的吗?为什么静态字段不是个好主意,我应该怎么做呢?

(类似的问题建议使用属性,但JavaFx没有NodePropertyAnchorPaneProperty)。

最佳答案

对于这个论坛,这个问题可能太基于观点了,但是我认为我在这里表达的观点被广泛接受,足以被接受。


  为什么静态字段是个坏主意


假设您在这里做了您想做的事情,并且允许它工作。假设您的老板在六个月内来到您的办公室,并说“客户喜欢该应用程序,但他们希望能够同时打开多个节点编辑器。您能否制作该应用程序以便他们可以打开新窗口,每个都有一个节点编辑器?”

这种事情一直在现实生活中发生。

因此,从理论上讲,这应该很容易。您拥有定义布局的FXML和定义了与之关联的逻辑的控制器。因此,您所需要做的就是拥有一个事件处理程序(在菜单上说),该事件处理程序将创建新的StageScene,再次加载FXML,并将场景的根设置为FXML的根。

除非它不起作用。问题是,您将根窗格设置为static。因此,当您再次加载FMXL时,它将用新加载的FXML中的新值替换canvas的当前值。如果现在尝试将新元素添加到第一个画布,则不能。

因此,现在您必须重构代码,以便canvas是一个实例变量。更糟糕的是,您通过static getCanvas()方法公开公开了该方法,该方法可能已在应用程序中的任何位置调用。因此,您必须跟踪所有这些调用。您最终在凌晨3点尝试尝试重复整个代码库,以找出必须更改的内容。

使事物静态化的问题(一个问题)是,您只承诺拥有该变量的一个副本,并且从根本上讲,您一直都致力于该副本(或者如果您改变主意,则承诺重写许多应用程序)。该决定向上泄漏:仅拥有一个画布,就只能拥有一个控制器,因此只能拥有一个节点编辑器。实质上,您已阻止所编写的代码可重复使用。



您的基本假设是错误的。 static关键字确实与可访问性无关:它与范围有关。 static字段的作用域为该类:非静态字段的作用域为该类的每个实例。您通过定义公共的getCanvas()方法并使该方法的范围(类)可用(通过将该类公开)来使字段可访问。如果canvas是实例变量,则可以通过类似地定义一个公共getCanvas()方法并使该方法的范围(现在是CanvasController实例)可用来使其可访问。因此,您加载FXML,通过在getController()上调用FXMLLoader检索控制器,然后将控制器实例传递给需要访问它的任何人。注意,现在您可以在代码中控制谁收到了对控制器的引用,并且如果需要进行任何重构,则至少要遵循一条路径来查找控制器的使用位置。

您提到“ JavaFX没有NodePropertyAnchorPaneProperty:它具有ObjectProperty,因此如果需要,可以使用ObjectProperty<Node>ObjectProperty<AnchorPane>



不过,总的来说,我认为将视图元素(如您的canvas)暴露在控制器之外,甚至与应用程序的其他部分共享控制器也是一个坏主意。相反,您应该考虑使用MVC类型的方法。您的问题中缺少的是“ M”:模型。因此,您的模型将使用带有ImageScaleComposite等类的对象模型。这些类应使用JavaFX properties使它们可观察,并使用ObservableList(及类似方法)存储这些对象的集合对象和它们之间的关系。创建一个模型实例并将其传递给您的控制器。控制器可以观察模型中的数据,并在视图更改时更新视图,并根据用户输入更新模型。然后与需要访问它的应用程序的其他部分共享模型实例。这样可以使事情更易于维护:例如,如果您确定canvas需要是Pane而不是AnchorPane,则该更改现在仅限于FXML和控制器,并且不会泄漏到其余部分您的应用程序。 this question中有一个(更简单的)JavaFX中的MVC(实际上是更多的MVP)示例。

关于java - (JavaFx)正确的方式表示静态FXML字段(以及为什么这是一个坏主意),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41720572/

相关文章:

java - 如何在java中填充多边形?

java - 根据JavaFX和OSGI开发指导

java - 解释大 O 循环和数组

text - JavaFX:设置文本控件的背景颜色

java - 无法加载资源 Jar 文件

c++ - 需要处理 C++ 类成员的静态函数

c++ - 初始化没有零参数构造函数的静态类对象c++

java - 为什么多个小程序可以访问一个全局类?

java - 如何在 Windows 机器上检查 java 无限强度加密策略

java - 尽管将SQL数据库链接到我的JavaFx程序但仍尝试登录却抛出错误