gpt4 book ai didi

java - 从 fxml 实例化的 ObservableArrayList 的返回值不符合预期

转载 作者:行者123 更新时间:2023-11-30 08:19:43 25 4
gpt4 key购买 nike

我正在尝试将字符串变量列表传递到 fxml 中的自定义 Controller ,因此:

<Pane xmlns:fx="http://javafx.com/fxml" >
<VBox fx:id="vbox">
<StepChart fx:id="employment" title="Unemployment" enabled = "true" prefHeight="250.0" prefWidth="300.0">
<statistics>
<FXCollections fx:factory="observableArrayList" >
<String fx:value="employees"/>
<String fx:value="farms"/>
</FXCollections>
</statistics>
</StepChart>
</VBox>
</Pane>

统计信息在 StepChart 中被标记为 @DefaultProperty,但为了完整起见包含在此处。在 StepChart 中,我按如下方式获取可观察列表值:

ArrayList<String> list = new ArrayList<String>();
ObservableList<String> statistics = FXCollections.observableArrayList(list);

statistics.addListener(new ListChangeListener<String>()
{
@Override
public void onChanged(ListChangeListener.Change<? extends String> change)
{
for(String s: statistics)
{
System.out.println("s: " + s);
}
}
});

这一切都完美无缺,除了 fxml 生成的不是一个单独的字符串列表,而是一个单独的字符串,其中包含 fxml 值:

s: [employees, farms]

尽管Introduction to fxml说它“创建了一个可观察数组列表的实例,其中填充了三个字符串值”。我是否遗漏了一些有关如何处理可观察列表的信息,或者这是预期的行为?

最佳答案

我怀疑你的StepChart类没有 setStatistics(...)方法。 FXMLLoader将以特殊方式处理它,如下所示:

通常,当 FXMLLoader遇到这样的结构:

<ClassName fx:id="ref">
<propertyName>
<AnotherClass />
</propertyName>
</ClassName>

它执行的代码可以转换成如下内容:

ClassName ref = new ClassName();
ref.setPropertyName(new AnotherClass());

(不是字面意思,它做的是等效的,但使用了反射)。

在大多数情况下,如果没有 setPropertyName(...)在指定的类中定义,将抛出异常。

只读列表被视为一种特殊情况:所以如果 ClassName定义一个 List getList() {...}方法,没有 void setList(List aList) {...}方法,那么以下仍然有效:

<ClassName fx:id="ref">
<list>
<!-- values -->
</list>
</ClassName>

处理方式,在这种特殊情况下(属性的名称对应于类型为 List 的属性,有 get 方法,没有 set 方法),然后是 FXMLLoader执行以下伪代码:

ClassName ref = new ClassName();
for (Object item : itemsDefinedInsideListElement) {
ref.getList().add(item);
}

哪里for循环遍历 <list> 中定义的所有元素元素。这使您能够做类似的事情

<HBox>
<children>
<Label/>
<TextField/>
</children>
</HBox>

即使HBox没有setChildren()方法。

因此,对于您的 FXML,假设 StepChart没有setStatistics(...)方法,FXMLLoader遍历 <statistics> 的所有直接子元素, 将每一个传递给 getStatistics().add(...)StepChart 上调用它创建的实例。在本例中,只有一个子元素,即 ObservableList<String>。 .

FXMLLoader也足够聪明,可以在运行时确定列表的通用类型(我实际上不知道它是如何做到的)。因为它看到列表期待一个 String ,并且该元素未解析为 String ,它会尝试将其强制转换为正确的类型。强制转换为 String很简单:它只调用 toString在创建列表的结果上,并将结果传递进来。所以你最终得到一个包含单个 String 的列表。 : 那String是调用 toString 的结果在 List 上包含元素“employees”和“farms”。等效的 Java 代码看起来像

StepChart employment = new StepChart();
employment.getStatistics().add(Arrays.asList("employees", "farms").toString());

所以你看到了单个元素 "["employees", "farms"]"作为statistics的内容.

您有两个修复程序,您选择的那个应该取决于您要在 StepChart 中公开的 API。 .您可以添加 setStatistics(ObservableList<String>)方法。然后 FXMLLoader将创建列表,并将其传递给该方法。

或者,您可以继续省略 setStatistics(...)方法(即保留 statistics 作为只读列表属性)并将 FXML 修改为

  <StepChart fx:id="employment"  ... >
<statistics>
<String fx:value="employees"/>
<String fx:value="farms"/>
</statistics>
</StepChart>

这样你就可以使用 FXMLLoader的只读列表属性机制。

关于java - 从 fxml 实例化的 ObservableArrayList 的返回值不符合预期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26614677/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com