簡體   English   中英

帶有地圖的JavaFX TableView對象

[英]JavaFX TableView Objects with Maps

所以我在JavaFx TableView上做了一些挖掘,我找到了一些很好的解決方案來處理簡單的情況。

本文提供了如何使用Person對象創建表的一個很好的解釋,並且還展示了如何使用Map創建表。

這是我的問題,假設我有一個Object Person,它包含一些簡單的成員數據,還有一個Level to Assignments to Grades。

例:

public class Person {
   String firstName;
   String lastName;
   String age;
   Map<Assignment, Grade> map;
 }

我想顯示如下表格

firstName |  lastName | age | Assignment1 | Assignment 2 | Assignment 3 | ...

如果我像這樣定義一個表:

private TableView<Student> table;

很容易定義簡單的列,如:

private TableColumn<Student, String> firstNameColumn =
     firstNameColumn.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));

但是,我應該如何為地圖中的每個鍵定義列?

這甚至是可能的還是我應該創建另一個處理地圖的表?

您不必使用默認的PropertyValueFactory,您可以編寫自己的回調。

import java.util.HashMap;
import java.util.LinkedHashMap;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;

public class AssTable extends Application {

    @Override
    public void start(Stage primaryStage) {
        ObservableList<Student> students = FXCollections.observableArrayList(
            new Student("jack"),new Student("john"),new Student("jill"),new Student("jane"));
        TableView<Student> studentTable = new TableView(students);
        TableColumn<Student, String> firstNameColumn = new TableColumn("name");
            firstNameColumn.setCellValueFactory(new PropertyValueFactory("firstName"));
        studentTable.getColumns().add(firstNameColumn);

        int maxAss = 0;
        for (Student student : students)
            maxAss = Math.max(maxAss, student.map.size());

        Callback<TableColumn.CellDataFeatures<Student, String>, ObservableValue<String>> callBack = 
                new Callback<TableColumn.CellDataFeatures<Student, String>, ObservableValue<String>>() {
            @Override
            public ObservableValue<String> call(TableColumn.CellDataFeatures<Student, String> param) {
                return param.getValue().map.containsKey(
                        "ass"+Integer.toString((int)param.getTableColumn().getUserData()))
                        ? new SimpleStringProperty(String.format("%.1f",100d*param.getValue().map.get(
                            "ass"+Integer.toString((int)param.getTableColumn().getUserData()))))
                        :new SimpleStringProperty("");
            }
        };

        ObservableList<TableColumn<Student, String>> assCols = FXCollections.observableArrayList();
        for (int i = 1; i<=maxAss; i++){
            TableColumn<Student, String> tmpCol = new TableColumn("ass"+Integer.toString(i));
            tmpCol.setUserData(i);
            tmpCol.setCellValueFactory(callBack);
            assCols.add(tmpCol);
        }
        studentTable.getColumns().addAll(assCols);

        VBox root = new VBox(studentTable);
        Scene scene = new Scene(root, 500, 250);

        primaryStage.setTitle("Table with map");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public class Student {

        private final StringProperty firstName = new SimpleStringProperty();
        public StringProperty firstNameProperty(){return firstName;}
        public final HashMap<String, Double> map;

        public Student(String fn) {
            firstName.set(fn);
            map = new LinkedHashMap<>();
            for (int i = 1; i <= 10; i++) {
                double grade = Math.random();
                if (grade > .5) {
                    map.put("ass" + Integer.toString(i), grade);
                }
            }
        }
    }
}

屏幕截圖

您可以看到它根據分配的數量添加列。 此隨機樣本中也沒有人做過ass4。 使用此代碼和示例,您無法添加#8之類的分配而不添加新列,或者它不會顯示。

我假設每個Map的大小(條目數)在運行時沒有變化,或者更好:有一個固定的最大條目。 如果是這種情況, TableView可以使用與標准屬性(或Property )相同的方式訪問每個Entry 這是一個修改過的Person類。

public class PersonSimple {
String firstName;
String lastName;
String age;
Map<Integer, Double> map;

public PersonSimple(String fn, String ln, String age, Double gr0, Double gr1, Double gr2)
{
    this.firstName = fn;
    this.lastName = ln;
    this.age = age;
    map = new LinkedHashMap<>();
    map.put(0, gr0);
    map.put(1, gr1);
    map.put(2, gr2);
}

public String getFirstName()
{
    return firstName;
}

public String getLastName()
{
    return firstName;
}
public String getAge()
{
    return age;
}

private Double getFromMap(Integer key)
{
    Set<Entry<Integer, Double>> s = map.entrySet();
    Iterator<Entry<Integer, Double>> iter = s.iterator();
    int index = 0;
    while(iter.hasNext())
    {
        Entry<Integer, Double> e = iter.next();
        if(index == key.intValue())
        {
            return e.getValue();
        }
        index++;
    }
    return null;
}

public Double getFM0()
{
    return getFromMap(0);
}

public Double getFM1()
{
    return getFromMap(1);
}

public Double getFM2()
{
    return getFromMap(2);
}

}

如您所見,每個PersonSimple都有一個必須包含三個條目的Map 現在來了訣竅。 對於每個條目,您都定義了一個get方法。 請注意如何命名它們,因為這部分對於與TableView的交互至關重要。

以下代碼顯示了如何將這些新方法連接到TableView

 TableColumn firstNameCol = new TableColumn("First Name");
    TableColumn lastNameCol = new TableColumn("Last Name");
    TableColumn ageCol = new TableColumn("Age");
    TableColumn aCol = new TableColumn("Assignment1");
    TableColumn bCol = new TableColumn("Assignment2");
    TableColumn cCol = new TableColumn("Assignment3");

    table.getColumns().addAll(firstNameCol, lastNameCol, ageCol,aCol,bCol,cCol);

    firstNameCol.setCellValueFactory(new PropertyValueFactory<Person,String>("firstName"));
    lastNameCol.setCellValueFactory(new PropertyValueFactory<Person,String>("lastName"));
    ageCol.setCellValueFactory(new PropertyValueFactory<Person,String>("age"));

    aCol.setCellValueFactory(new PropertyValueFactory<Person,Double>("FM0"));
    bCol.setCellValueFactory(new PropertyValueFactory<Person,Double>("FM1"));
    cCol.setCellValueFactory(new PropertyValueFactory<Person,Double>("FM2"));

非常重要的是,每個PropertyValueFactor都會獲得一個適合PersonSimple類中其中一個get方法的PersonSimple 有關詳細信息,請參閱TableView-API

當然,我的方法並沒有解決從動態映射中獲取數據的問題,因為據我所知,Java在運行時期間無法向類中添加新方法。 但是可能有一個技巧使用reflection-api來規避這種限制。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM