【问题标题】:JavaFX - Label -- How to Access Class MemberJavaFX - 标签 - 如何访问类成员
【发布时间】:2012-09-10 05:11:25
【问题描述】:

所以我的问题很简单。当他们是String 而不是Label 时,我可以在单独的类中访问类成员,但是当他们 @987654324 时,我似乎无法访问@。使用 JDK 7u6(带 JavaFX 2.2)。

简单的例子。第一个有效,第二个无效。 foo.label 可以在第一个示例中分配,但我在第二个示例中得到一个 NullPointer。谁能解释为什么foo.label 在下面的第二个示例中为空?

更新:我从原始问题中删除了 @FXML 注释,因为我认为它们对于我遇到的问题不是必需的。另外,请参阅我对answer by @jewelsea 的评论...最后,为了完整起见,我添加了我的 FXML 文件(在 Q 的底部)。

这行得通:

// Example 1:
public class SampleController implements Initializable {
    Foo foo = new Foo();

    public void handleButtonAction(ActionEvent event) {
        System.out.println("You clicked me!");
        foo.label = "Hello World!";
        System.out.println(foo.label);
    }

    @Override public void initialize(URL url, ResourceBundle rb) {
    }    
}

// Example 1 -- Foo.java:
public class Foo {
    public String label;
}

而这行不通

// Example 2:
public class SampleController implements Initializable {
    Foo foo = new Foo();

    public void handleButtonAction(ActionEvent event) {
        System.out.println("You clicked me!");
        foo.label.setText("Hello World!");  // gives NullPointer exception !!
    }

    @Override public void initialize(URL url, ResourceBundle rb) {
    }    
}

// Example 2 -- Foo.java:
import javafx.scene.control.Label;

public class Foo {
    public Label label;
}

这是我的 FXML 文件,用于上述任一示例:

<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml" fx:controller="javafxapplication4.SampleController">
    <children>
        <Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" />
        <Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" text="hey!" />
    </children>
</AnchorPane>

【问题讨论】:

    标签: label javafx-2 fxml


    【解决方案1】:

    在您的第二个示例中,您从未将 foo 标签初始化为任何内容,因此它将保持为空。

    您确实使用Foo foo = new Foo(); 创建了一个Foo 对象,但这不会初始化Foo 内部的标签字段成员。特别是,@FXML 注释不会以您在提供的代码中使用它的方式做任何事情。这是因为 Foo 不是控制器。

    让您的示例运行的一些方法:

    1.摆脱 Foo

    • @FXML public Label label; 移动到您的SampleController
    • 摆脱Foo 类并确保您的fxml 定义fx:id="label"

    2.在 SampleController 中初始化 Foo 标签

    • 将以下代码放入示例控制器的初始化方法中:foo.label = new Label();
    • 此外,在初始化时,将 foo 标签添加到某个容器(例如布局窗格)中,使其可见。

    3.使 Foo 成为嵌套控制器

    • 保留 Foo 类。
    • 使用 @FXML Foo foo; 而不是 Foo foo = new Foo(); 在控制器中初始化 Foo 实例。
    • 使 Foo 类成为控制器(实现 Initializable 或定义具有适当签名的初始化方法)。
    • 在引用SampleController 的fxml 中,还有一个fx:include 语句用于新的foo.xml 文档,该文档设置fx:id="label" 以允许初始化Foo 实例。

    第三种方式似乎与您想要的最接近,它的文档位于 FXML 文档简介的 Nested Controllers 部分。

    注意: 这个问题更多的是关于如何使用@FXML 初始化类的成员,然后是如何访问类成员。访问只是通过普通的 getter/setter 或成员字段访问,就像您在示例中已经拥有的那样。

    您的第一个示例有效,因为您在使用之前明确地将 foo.label 初始化为一个新字符串(使用 foo.label = "Hello World!";)。

    【讨论】:

    • 谢谢jewelsea。我想序列化我的舞台/对话框的大多数属性,这样我就可以将它们保留在应用程序的后续运行中。我认为最简单的方法(我不担心性能)是仅将属性(来自控制器)“剥离”到一个单独的对象中,然后将其序列化。按照您的建议,我想我应该将所有属性作为 FXML 属性保留在原始控制器上。在这种情况下,这些属性的自动填充可以在控制器的初始化中发生,此时它将反序列化并填充它们。
    • 如果你实现了,请告诉我你是如何序列化 javafx.beans.property 对象的。我不相信这是可能的
    • @jewelsea 我想使用我的 FXML 文件已经创建的标签(我在上面添加了它)。如果我使用您的答案 2.,标签是可用的,但它不会出现在我的表单上(当然)。有没有办法访问 fx:id 'label' 并更改其文本字段(从 'Hey!' 到其他内容,例如我的示例中的 'Hello World!')?
    • 在初始化方法中写入foo.label.setText("Hello World!");,或者您可以使用fxml documentation中描述的资源包。
    • 我想你已经回答了我的问题,这是我的错误信念,我认为我可以“使用我的 FXML 文件已经创建的标签”......这可以做不完。 IOW,“反序列化”方法不能简单地写回这些字段/属性。我必须编写一个自定义反序列化(或去外部化),对每个属性执行myFxmlField.setText(text read from InputStream);。至少,我是这么认为的!再次感谢珠宝海。
    【解决方案2】:

    伙计,你把事情搞混了!但它确实发生了。

    首先,在示例1中:

    public String label;
    

    是字符串而不是标签。而且我很确定你没有在 FXML 文件中使用字符串(不是你不能,但它根本不会显示在舞台中)

    无论如何,当您使用“=”符号时,您正在初始化您的字符串,当您将 @FXML 放在不实现 Initializable 接口的类中时,您不会从 FXML 初始化任何内容文件(顺便说一句,它必须引用一个 Initializable 作为它的控制器),因此,您引用的是一个空对象。

    要解决示例 2 中的问题,您需要:

    // 示例2:

    import javafx.fxml.FXML;
    import javafx.scene.control.Label;
    
    public class SampleController implements Initializable {
        @FXML public Label label;
    
        @FXML private void handleButtonAction(ActionEvent event) {
            System.out.println("You clicked me!");
            foo.label.setText("Hello World!");  // gives NullPointer exception !!
        }
    
        @Override public void initialize(URL url, ResourceBundle rb) {
        }    
    }
    

    并确保您有一个 FXML 文件,例如:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.control.Label?>
    <?import javafx.scene.layout.AnchorPane?>
    <?import javafx.scene.control.Button?>
    
    <AnchorPane xmlns:fx="http://javafx.com/fxml" fx:id="whatever-id" fx:controller="samplecontroller.package.SampleController">
       <children>
          <Label fx:id="label" text="not really necessary" />
          <Button fx:id"btnLabelChanger" onmouseclick="#handleButtonAction"/>
       </children>
    </AnchorPane>
    

    我希望它有所帮助。干杯。

    【讨论】:

    • 欣赏这些想法,布鲁诺。但是不,我的问题的重点是当有一个 separate 类(在我的示例中称为 Foo )时,我如何访问 Label 字段?当它是一个字符串时我可以访问它(如示例 1 所示),但当它是一个标签时我不能。我认为您在说“当您将@FXML 放在不实现 Initializable 接口的类中时,您没有从您的 FXML 文件中初始化任何内容”时暗示了我的问题,但我相信 Jewelsea 有一个答案可以引导我更接近我的需要。我对他们的回答的评论描述了为什么我想要一个单独的课程。
    • 好吧,你的问题是:谁能解释为什么 foo.label 在下面的第二个示例中为空?
    • 没错,我确实问过这个问题。我还澄清了在顶部说 in a separate class 的问题,并且我还添加了我的 FXML 文件。谢谢。赞成解释空部分!
    猜你喜欢
    • 1970-01-01
    • 2016-05-21
    • 2014-06-09
    • 2011-04-18
    • 2012-10-18
    相关资源
    最近更新 更多