首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JavaFX -你如何在科特林使用MapValueFactory?

JavaFX -你如何在科特林使用MapValueFactory?
EN

Stack Overflow用户
提问于 2022-05-10 21:01:30
回答 1查看 99关注 0票数 2

我正试图在科特林的MapValueFactory上使用TableView。我在https://jenkov.com/tutorials/javafx/tableview.html的Java中找到了一个很好的例子

以下Java代码运行良好:

代码语言:javascript
复制
package com.example.tableview;

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.MapValueFactory;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class HelloApplication extends Application {
    @Override
    public void start(Stage stage) throws IOException {

        var tableView = new TableView();

        TableColumn<Map, String> firstNameColumn = new TableColumn<>("firstName");
        firstNameColumn.setCellValueFactory(new MapValueFactory<>("firstName"));

        TableColumn<Map, String> lastNameColumn = new TableColumn<>("lastName");
        lastNameColumn.setCellValueFactory(new MapValueFactory<>("lastName"));

        tableView.getColumns().add(firstNameColumn);
        tableView.getColumns().add(lastNameColumn);

        ObservableList<Map<String, Object>> items = FXCollections.<Map<String, Object>>observableArrayList();

        Map<String, Object> item1 = new HashMap<>();
        item1.put("firstName", "Randall");
        item1.put("lastName" , "Kovic");

        items.add(item1);

        Map<String, Object> item2 = new HashMap<>();
        item2.put("firstName", "Irmelin");
        item2.put("lastName" , "Satoshi");

        items.add(item2);

        tableView.getItems().addAll(items);
        Scene scene = new Scene(tableView, 320, 240);
        stage.setTitle("Hello!");
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

当我将该代码剪切并粘贴到IntelliJ中的Kotlin项目中时,它会尝试从Java自动转换到Kotlin。但是,生成的代码不会编译。它说,试图将firstNameColumn添加到tableView.columns中存在类型不匹配。

代码语言:javascript
复制
Type mismatch.
Required: Nothing!
Found: TableColumn<Map<*, *>, String>

以下是未编译的生成的Kotlin代码:

代码语言:javascript
复制
package com.example.tableview

import javafx.application.Application
import javafx.collections.FXCollections
import javafx.scene.Scene
import javafx.scene.control.TableColumn
import javafx.scene.control.TableView
import javafx.scene.control.cell.MapValueFactory
import javafx.stage.Stage

class HelloApplication : Application() {

    override fun start(stage: Stage) {

        val tableView: TableView<*> = TableView<Any?>()

        val firstNameColumn = TableColumn<Map<*, *>, String>("firstName")
        firstNameColumn.setCellValueFactory(MapValueFactory("firstName"))

        val lastNameColumn = TableColumn<Map<*, *>, String>("lastName")
        lastNameColumn.setCellValueFactory(MapValueFactory("lastName"))

        tableView.columns.add(firstNameColumn)
        tableView.columns.add(lastNameColumn)

        val items = FXCollections.observableArrayList<Map<String, Any>>()

        val item1: MutableMap<String, Any> = HashMap()
        item1["firstName"] = "Randall"
        item1["lastName"] = "Kovic"

        items.add(item1)

        val item2: MutableMap<String, Any> = HashMap()
        item2["firstName"] = "Irmelin"
        item2["lastName"] = "Satoshi"

        items.add(item2)

        tableView.items.addAll(items)
        val scene = Scene(tableView, 320.0, 240.0)
        stage.title = "Hello!"
        stage.scene = scene
        stage.show()

    }

    fun main() {
        Application.launch(HelloApplication::class.java)
    }
}

任何帮助都将不胜感激。我已经在这上面挖了好几个洞试图让类型正确..。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-05-10 22:11:56

编译器错误

您的编译器错误来自您使tableView成为TableView<*>这一事实。它对这些类型不太了解,无法将任何内容添加到列列表中。只需更改这一行:

代码语言:javascript
复制
val tableView: TableView<*> = TableView<Any?>()

致下列之一:

代码语言:javascript
复制
val tableView: TableView<Map<*, *>> = TableView()
// or
val tableView = TableView<Map<*, *>>()

将让您的Kotlin代码编译,并按预期运行。

Java代码的问题

您的Java代码编译,因为在那里,您将tableView设置为原始类型的TableView。这意味着不使用与TableView关联的泛型。除非您与早于Java 5的遗留代码交互,否则不应该使用原始类型。

你应该改变:

代码语言:javascript
复制
var tableView = new TableView();

至:

代码语言:javascript
复制
var tableView = new TableView<Map<?, ?>>();

注意,在参数化TableColumn的时候,您也使用了原始类型。修复类似,但不幸的是,由于它在实现Callback时声明了一个原始类型,它破坏了使用Callback的能力。真正的解决办法是不使用MapValueFactory (见下文)。

不要使用*ValueFactory

PropertyValueFactoryMapValueFactory这样的类是在lambda表达式(在Java中)不是一件事的时候添加的。这意味着使用匿名类。匿名类可能非常冗长,因此它们添加了方便类,以使开发人员更容易编写代码。但是它们有两个缺点:它们依赖于反射,更重要的是,您将失去所有编译时验证(例如,属性是否存在、属性的类型等等)。

在Java和Kotlin中,我建议使用lambda表达式(同时也从不使用原始类型)。

爪哇:

代码语言:javascript
复制
// Note everywhere is using a Map<String, String> now
var tableView = new TableView<Map<String, String>>();

TableColumn<Map<String, String>, String> firstNameColumn = new TableColumn<>("firstName");
firstNameColumn.setCellValueFactory(data -> new SimpleStringProperty(data.getValue().get("firstName")));

TableColumn<Map<String, String>, String> lastNameColumn = new TableColumn<>("lastName");
lastNameColumn.setCellValueFactory(data -> new SimpleStringProperty(data.getValue().get("lastName")));

科特林:

代码语言:javascript
复制
// Again, note everywhere is using Map<String, String>
val tableView = TableView<Map<String, String>>()

val firstNameColumn = TableColumn<Map<String, String>, String>("firstName")
firstNameColumn.setCellValueFactory { SimpleStringProperty(it.value["firstName"]) }

val lastNameColumn = TableColumn<Map<String, String>, String>("lastName")
lastNameColumn.setCellValueFactory { SimpleStringProperty(it.value["lastName"]) }

虽然我在这两个版本中都使用了Map<String, String>,但显然可以通过不同的方式参数化Map以满足您的需要。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72192897

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档