当前位置: 首页 > 知识库问答 >
问题:

Scala中的JavaFX 2和setCellValueFactory()?

陈琪
2023-03-14

我试图遵循以下JavaFX2指南:

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行导致:

错误:类类型需要,但javafx.scene.control.cell.属性值工厂[com.myapp.models.Foo,_]找到c.setCellValueFactory(新属性值工厂,_)

我不明白我该如何使用这种方法。如果我用字符串替换,那么我得到:

错误:类型不匹配;发现:javafx。场景控制单间牢房PropertyValueFactory[com.myapp.models.Foo,String]必需:javafx。util。回调[javafx.scene.control.TableColumn.CellDataFeatures[com.myapp.models.Foo,?0],javafx。豆。价值ObservalEvalue[?0]]类型在哪里?0 c.setCellValueFactory(新属性ValueFactoryFoo,字符串)

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

共有2个答案

吕博耘
2023-03-14

我建议尝试使用长格式的PropertyValueFactory
(很抱歉,我不熟悉用Java编写的Scala)

 c.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Foo, String>,
             ObservableValue<String>>() {
     public ObservableValue<String> call(TableColumn.CellDataFeatures<Foo, String> f) {
         // f.getValue() returns the Foo instance for a particular TableView row
         return f.getValue().messageProperty();
         // or
         return new SimpleStringProperty(p.getValue().getMessage());
         // if you omit messageProperty() in Foo model class.
         // However omitting it, causes the property listener could not be attached resulting 
         // unable to refresh (synchronize) tableview row item value when the backing 
         // Foo's message value is changed.
     }
  });

请注意,您的Foo模型必须类似于:

public class Foo {
    private SimpleStringProperty message;

    public SimpleStringProperty messageProperty() {
        return message;
    }

    public String getMessage() {
        return message.get();
    }

    public void setMessage(String message) {
        this.message.set(message);
    }
}
孔深
2023-03-14

TL;DR:在java中,在类型参数方面悄悄绕过类型安全是很容易的。Scala不会让你这么做,除非你执行显式的强制转换。此外,使用表。getColumns检索列意味着我们将丢失单元格类型。解决方案:将TableColumn实例转换为适当的类型,或者手动实例化该列。

第一个问题在于表的签名。getColumns:它返回一个可观察列表[TableColumn[S,]](参见http://docs.oracle.com/javafx/2/api/javafx/scene/control/TableView.html#getColumns()). 因此,您的cval被键入为TableColumn[Foo,]。这意味着您将丢失单元格内容的类型(由第二个类型参数表示)。

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

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

这很符合逻辑:您有一个列列表,其中每列可以包含不同类型的对象。对于包含不同类型对象的scala列表,我们将面临同样的困境,这些对象都是先验未知的:只有类型转换(或类型匹配,这是伪装的转换)才能让您在编译时返回特定类型。

还请注意,在web上的许多JavaFx示例中,人们不会通过表检索列。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仅被键入为TableColiv而不是TableColiv

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,2;

 类似资料:
  • 我如何创建一个组合框,它有不同的显示值和实际值的项目?

  • 希望我能把问题弄得尽可能清楚。我正在使用JavaFX库为GUI开发一个小型java应用程序。我正在做一个POP连接,并将消息存储为ObservableList。为此,我使用javax.mail。我将这个observablelist传递给一个tableview,并通过以下方式将所需的值传递给TableColumns: Subject和sentDate是完美的读入。但不幸的是,“from”将对象引用添

  • 这将返回一个图表对象。我如何将它与我的JavaFx节点(如HBox等)集成?

  • 我必须找到新的Java桌面应用程序的技术。我不想使用swing,但我找不到好的和透视图的替代方案。我了解JavaFX,但我有很强的要求:它必须看起来很好,而不是在linux、windows和Macox上。JavaFX在每个平台上都能正常工作吗?我在使用JavaFX时会发现哪些大麻烦?

  • 我注意到在JavaFX1.x中,脚本语言允许非常简单的字符串国际化。JavaFX2中有类似的特性吗? 基本上:国际化JavaFX2应用程序的最佳实践是什么?

  • 问题内容: 我有一个TextField可以输入搜索词,还有一个“ Go”按钮。但是在JavaFX2中,我如何做到这一点,以便在TextField中按Enter键可以执行操作? 谢谢 :) 问题答案: 您可以使用TextField的onAction属性并将其绑定到控制器中的方法。 在您的FXML文件中: