我正在尝试遵循此 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/