我如何将 propertyvaluefactory 指向地图的值? [英] How do i point a propertyvaluefactory to a value of a map?

查看:38
本文介绍了我如何将 propertyvaluefactory 指向地图的值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

而不是将 propertyvaluefactory 指向对象的属性,如下所示:

Instead of pointing a propertyvaluefactory to a property of an object as follows:

traineeCol.setCellValueFactory(new PropertyValueFactory("sumName"));

我需要它指向地图内的一个属性,而地图又是它在上面的代码中已经指向的对象的一个​​属性.这可能吗?

I need it to point to a property inside a map, the map in turn is a property of the object it already is pointing to in the code above. Is this possible?

添加了相关对象的代码.所以基本上,我需要 PropertyValueFactory 指向具有给定键的整数,键是列标题.

edit: added code of the object in question. So basically, i need the PropertyValueFactory to point toward the Integer with given key, the key being the column header.

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package models;

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import database.DAO;
import java.util.Map;

/**
 *
 * @author Jasper
 */
public class Trainee {
    private final StringProperty firstName;
    private final StringProperty tussenVoegsel;
    private final StringProperty lastName;
    private final StringProperty branch;
    private final StringProperty sumName;
    private final Map<String, Integer> trainingPassed;

    public Trainee(String firstName, String tussenVoegsel, String lastName, String branch)
    {
        this.firstName = new SimpleStringProperty(firstName);
        this.tussenVoegsel = new SimpleStringProperty(tussenVoegsel);
        this.lastName = new SimpleStringProperty(lastName);
        this.branch = new SimpleStringProperty(branch);
        trainingPassed = new DAO().loadTrainingPassed(lastName);

        this.sumName = new SimpleStringProperty(this.firstName.get() + " " +
                this.tussenVoegsel.get() + " " + this.lastName.get());
    }

    public String getFirstName() {
        return firstName.get();
    }

    public String getTussenVoegsel() {
        return tussenVoegsel.get();
    }

    public String getLastName() {
        return lastName.get();
    }

    public String getBranch() {
        return branch.get();
    }

    public String getSumName() {
        return sumName.get();
    }

    public Map<String, Integer> getTrainingPassed() {
        return trainingPassed;
    }

}

Edit2:增加tableview的代码区,包括声明等

Added code area of tableview, including declarations etc.

@SuppressWarnings("unchecked")
    private TableView table() {
        TableView tableCourseCategories = new TableView();
        ArrayList<TableColumn> colList = new ArrayList<>();

        TableColumn traineeCol = new TableColumn("Training");
        traineeCol.setMinWidth(130);
        traineeCol.setCellValueFactory(new PropertyValueFactory("sumName"));

        for (Course course : courses) {
            if (course.getCategory().equals(this.category)) {
                TableColumn<Trainee, Number> tc = new TableColumn<>();
                tc.setEditable(true);
                tc.setMinWidth(130);
                tc.setText(course.getName());

//                tc.setCellValueFactory(new Callback<CellDataFeatures<Trainee>>, ObservableValue<Number>>() {
//                    @Override
//                    public ObservableValue<Number> call(CellDataFeatures<Trainee> data) {
//                        Integer value = data.getValue().getTrainingPassed().get("sumName");
//                        return new ReadOnlyIntegerWrapper(value);
//                    }
//                });

                colList.add(tc);
            }
        }

        tableCourseCategories.getItems().addAll(this.trainees);
        tableCourseCategories.getColumns().add(traineeCol);
        tableCourseCategories.getColumns().addAll(colList);

        return tableCourseCategories;
    }

推荐答案

我不会取消未检查"警告:没有理由不正确键入您的 TableViewTableColumns.

I would not suppress the "unchecked" warnings: there's no reason not to properly type your TableView and TableColumns.

TableColumn 中的 setCellValueFactory(...) 方法不需要采用 PropertyValueFactory:它可以采用任何 Callback<CellDataFeatures,ObservableValue.这里S是表格每一行显示的数据类型(即你使用的是TableView),而T是此列中显示的数据类型(即您使用的是 TableColumn).在您的情况下,STraineeTNumber.

The setCellValueFactory(...) method in TableColumn does not need to take a PropertyValueFactory: it can take any Callback<CellDataFeatures<S>, ObservableValue<T>>. Here S is the type of data displayed by each row of the table (i.e. you are using a TableView<S>), and T is the type of data displayed in this column (i.e. you are using a TableColumn<S,T>). In your case S is Trainee and T is Number.

这个 Callback 本质上只是一个函数,它将给定的行值(在你的情况下)转换为要在单元格中显示的值.它稍微复杂一些,因为行值被包裹在一个 CellDataFeatures 对象中,并且返回类型必须是一个包裹要显示的实际值的 ObservableValue.如果您想访问其他信息来计算您的值,则提供了 CellDataFeatures(它使您可以访问显示值的 TableColumnTableColumn 所在的 TableView).需要返回一个 ObservableValue,因为 TableCell 会观察值的变化并自动更新.

This Callback is essentially just a function that converts a given row value (Trainee in your case) to the value to be displayed in the cell. It's made slightly more complex in that the row value is wrapped in a CellDataFeatures object, and the return type is required to be an ObservableValue wrapping the actual value to be displayed. A CellDataFeatures is provided in case you want access to other information to calculate your value (it gives you access to the TableColumn in which the value is being displayed and the TableView in which the TableColumn is held). An ObservableValue is required to be returned as the TableCell will observe the value for changes and update automatically.

如果您只想要行值,而不关心知道您在哪个 TableViewTableColumn 中(或已经知道,这是常见的),您通过在 CellDataFeatures 对象上调用 getValue() 来获取行值(示例中的 Trainee).

If you only want the row value, and don't care about knowing which TableView or TableColumn you are in (or already know, which is usual), you get the row value (the Trainee in your example) by calling getValue() on the CellDataFeatures object.

如果您的值没有 ObservableValue(例如 Property),您可以将常规值包装在 ReadOnlyXXXWrapper 课程.

If you do not have an ObservableValue (e.g. a Property) for your value, you can wrap a regular value in one of the ReadOnlyXXXWrapper classes.

所以基本上你只需要一个 Callback 实现,它的 call(...) 方法根据行的值计算要显示的值.

So basically all you need is a Callback implementation whose call(...) method computes the value to display from the value for the row.

在您的示例中,call() 方法只需引用地图:

In your example, the call() method just has to refer into the map:

traineeCol.setCellValueFactory(new Callback<CellDataFeatures<Trainee>, ObservableValue<Number>>() {
    @Override
    public ObservableValue<Number> call(CellDataFeatures<Trainee> data) {
        Integer value = data.getValue().getTrainingPassed().get(course.getName());
        if (value == null) {
            value = 0 ;
        }
        return new ReadOnlyIntegerWrapper(value);
    }
});

在 Java 8 中这减少为

In Java 8 this reduces to

traineeCol.setCellValueFactory(data -> 
    new ReadOnlyIntegerWrapper(data.getValue().getTrainingPassed().getOrDefault(course.getName(),0)));

在许多示例中使用的 PropertyValueFactory 只是一个预定义的实现,它使用反射在提供的对象中查找返回可观察值的现有方法.Javadocs.恕我直言,它在 Java 8 中非常多余,因为您可以替换

The PropertyValueFactory which is used in many examples is just a pre-defined implementation that uses reflection to find an existing method in the supplied object that returns an observable value. The basic logic of what it does is outlined in the Javadocs. IMHO it's pretty redundant in Java 8 as you can replace

firstNameColumn.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));

firstNameColumn.setCellValueFactory(data -> data.getValue().firstNameProperty());

后者更不容易出错(一切都经过编译器检查:方法返回的类型以及此类方法存在的事实)以及执行速度更快(通常反射非常慢).

The latter is less error prone (everything is compiler-checked: the types of the method returns and the fact that such a method exists) as well as performing faster (reflection in general is pretty slow).

这篇关于我如何将 propertyvaluefactory 指向地图的值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆