我正在尝试遵循此 JavaFX 2 指南:

http://docs.oracle.com/javafx/2/ui_controls/table-view.htm#CJAGAAEE

我使用 Scala 而不是 Java,对我来说它看起来像这样:

<TableView fx:id="test">
     <columns>
         <TableColumn prefWidth="75.0" text="Message" />
     </columns>
</TableView>

和代码:
val c = test.getColumns.get(0) // Get the first column.
c.setCellValueFactory(new PropertyValueFactory[Foo, _]("message")) // Foo is my model with a single SimpleStringProperty called "message".

val observableFoos = FXCollections.observableList(foos)
test.setItems(observableFoos)

我遇到的问题是 setCellValueFactory 行导致:



我不明白我应该如何使用这种方法。如果我用 _ 替换 String ,那么我得到:



如果我删除 setCellValueFactory 行,我可以确认一切正常——我只是在表格中没有看到任何内容——只是像预期的那样空白行..

最佳答案

TL;DR: 在 java 中很容易绕过类型参数的类型安全。
Scala 不会让您这样做,除非执行显式转换。
此外,使用 Table.getColumns 检索列意味着我们丢失了单元格的类型。
解决方案:将您的 TableColumn 实例转换为正确的类型,或手动实例化该列。

第一个问题在于 Table.getColumns 的签名:它返回一个 ObservableList[TableColumn[S,_]](参见 http://docs.oracle.com/javafx/2/api/javafx/scene/control/TableView.html#getColumns ())。
所以你的 c val 被输入为 TableColumn[Foo,_]
这意味着您将丢失单元格内容的类型(由第二个类型参数表示)。

这里唯一的解决方案是使用强制转换正确键入列 ( c ):

val c = test.getColumns.get(0).asInstanceOf[TableColumn[Foo, String]]
c.setCellValueFactory(new PropertyValueFactory[Foo, String]("message"))

这是非常合乎逻辑的:您有一个列列表,其中每列可以包含不同类型的对象。对于包含不同类型对象的 Scala 列表,我们将面临同样的困境,所有对象都是先验未知的:只有强制转换(或类型上的匹配,这是变相的强制转换)才能让您在编译时取回特定类型时间。

另请注意,在网络上的许多 JavaFx 示例中,人们不会通过 Table.getColumns 检索列。相反,他们手动实例化它们,然后立即调用 setCellValueFactory
这样做可以解决您的问题(无需强制转换),因为您将自己指定类型参数:
val c = new TableColumn[Foo, String] // See ma, no cast!
c.setCellValueFactory(new PropertyValueFactory[Foo, String]("message"))

现在,您可能会查看一些 Java 示例,并注意到它们在实例化 TableColumn 时实际上并未提供 任何 类型参数:
TableColumn c  = new TableColumn();
c.setCellValueFactory( new PropertyValueFactory<Foo,String>("name"));

它确实可以编译。为何如此?可悲的事实是,上面的代码并不比进行强制转换更安全,因为它依赖于 Java 对预泛型感知类的向后兼容性。
换句话说,因为 c 的类型只是 TableColumn 而不是 TableColumn<?, String> 例如,java 编译器将其视为非泛型类,并且不对 TableColumn 的类型参数执行任何类型检查。
将此与将 c 的类型显式设置为泛型类型(但具有 unknwon 单元类型)时发生的情况进行对比:
TableColumn<Foo, ?> name  = new TableColumn("Name");
name.setCellValueFactory( new PropertyValueFactory<Room,String>("name"));

在这种情况下,编译器会发出类型不匹配错误:
error: method setCellValueFactory in class TableColumn<S,T> cannot be applied to given types;
...

这就像在 scala 中将 c 输入为 TableColumn[Foo, _]

关于Scala 中的 JavaFX 2 和 setCellValueFactory()?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12771556/

10-11 21:05