JavaFX使用OneToMany关系填充表格视图 [英] JavaFX populate tableview with a OneToMany relationship

查看:67
本文介绍了JavaFX使用OneToMany关系填充表格视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

用一个类中的数据填充表很容易,但是当我想用OneToMany关系中的数据填充表时又是什么呢?

例如:

班级人员: ID,名字,姓氏, 汽车(汽车与"Class Cars"之间有着千丝万缕的联系,因此一个人可以拥有一辆或多辆汽车)

现在,如果一个人有两辆车,如何将它添加到桌子上?

它应该看起来像这样:

ID  |  firstname  |  lastname  |  vehicleBrand(from cars)
==============================================
1   |  jack       | jackson    |  crysler
----------------------------------------------
    |             |            |  bmw
----------------------------------------------
2   |  sally      | jackson    |  ford

如果我有来自人"的可观察列表,则可以这样填充人数据:

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

但类似:

vehicleBrandCol.setCellValueFactory(
new PropertyValueFactory<Cars,String>("vehicleBrand")
);

vehicleBrandCol.setCellValueFactory(
new PropertyValueFactory<Person,String>("vehicleBrand")
);

不起作用.

以下答案适用于一个品牌.如果我尝试添加所有内容,则可以使用如下所示的循环进行尝试:

for (Car aCars : cars) {
                return new SimpleObjectProperty<>(aCars.vehicleBrand());
            }

但是循环不循环吗?! (我打印的是汽车尺寸,不是1)

解决方案

这应该是您所寻找的一部分,您可以执行以下操作:

  • 现在我假设您有两个类PersonCar.
  • Person类有一个ArrayList<Car>汽车.
  • Person类还具有方法getCars(),该方法返回此人的汽车收藏(ArrayList).

现在要从显示在TableView人中的Car类中获取品牌,您可以按以下方式设置CellValueFactory:

vehicleBrandCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Person,String>, ObservableValue<String>>() {
            @Override
            public ObservableValue<String> call(CellDataFeatures<Person, String> param) {
                ArrayList<Car> cars = new ArrayList<Car>();
                cars = param.getValue().getCars();
                if(cars!=null && !cars.isEmpty()) {
                    return new SimpleStringProperty(cars.get(0).getBrand());
                }
            }
        }
);

param.getValue()方法返回作为参数传递的person.

请注意,在此示例中,我仅返回(显示)当前人员的汽车集合中的第一个汽车品牌,您可以尝试使此示例适应您的情况.

好吧,这很有意义^^我应该列出 SimpleObjectProperty并返回它?

不,您不能这样做,因为您声明的列应包含String对象而不是List对象.

您可以做的是创建自定义单元格,该单元格将允许您显示每个Person实例的所有Car品牌,您可以查看

,然后您将需要自定义单元格来显示此ArrayList中包含的数据(汽车),因此请按以下方式设置CellFactory:

vehicleBrandCol.setCellFactory(column->{
            return new TableCell<Person, ArrayList<Car>>() {
                @Override
                protected void updateItem(ArrayList<Car> item, boolean empty) {
                    super.updateItem(item, empty);
                    if(item==null || empty) {
                        setGraphic(null);
                    } else {
                        VBox vbox = new VBox();
                        for(Car car : item) {
                            Label lbl = new Label(car.getBrand());
                            vbox.getChildren().add(lbl);
                        }
                        setGraphic(vbox);
                    }
                }
            };
        });

请注意,我正在创建VBox并使用标签,您可以使用任何喜欢的Node,例如,可以使用ListViewGridPane并将它们设置为Cell.

to populate a table is easy when you populate it with data from one class, but what is when I want to populate it with data from a OneToMany relationship?

for example:

Class Person: Id, firstname, lastname, cars(cars have a onetomany relationship with Class Cars, so one person can have one or more cars)

Now, if a person got two cars, how can I add this to a table?

It should look something like this:

ID  |  firstname  |  lastname  |  vehicleBrand(from cars)
==============================================
1   |  jack       | jackson    |  crysler
----------------------------------------------
    |             |            |  bmw
----------------------------------------------
2   |  sally      | jackson    |  ford

If I have the observable list from Person I can populate the person data like this:

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

but something like:

vehicleBrandCol.setCellValueFactory(
new PropertyValueFactory<Cars,String>("vehicleBrand")
);

or

vehicleBrandCol.setCellValueFactory(
new PropertyValueFactory<Person,String>("vehicleBrand")
);

does not work.

Edit: The answer below works for one brand. If I try to add all I tried it by using a loop like this:

for (Car aCars : cars) {
                return new SimpleObjectProperty<>(aCars.vehicleBrand());
            }

But the loop does not loop?! (I printed the size of cars and it is not 1)

解决方案

This should be part of what you are looking for, you can do this:

  • Now I'm supposing you have the two classes Person and Car.
  • The class Person has an ArrayList<Car> of cars.
  • The class Person has also a method getCars() which returns this person's collection (the ArrayList) of cars.

Now to get the brand from your Car class displayed in the TableView of persons you can set the CellValueFactory as follows:

vehicleBrandCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Person,String>, ObservableValue<String>>() {
            @Override
            public ObservableValue<String> call(CellDataFeatures<Person, String> param) {
                ArrayList<Car> cars = new ArrayList<Car>();
                cars = param.getValue().getCars();
                if(cars!=null && !cars.isEmpty()) {
                    return new SimpleStringProperty(cars.get(0).getBrand());
                }
            }
        }
);

The param.getValue() method returns the person passed as a parameter.

Notice that in this example I'm returning(displaying) only the first car brand from the collection of cars of the current person, you can try to adapt this example to your case.

Ok, that makes sense ^^ should I make a List of the SimpleObjectProperty and return this?

No you can't do this because you are declaring a column that should contain String objects not List objects.

What you can do is create custom cells that would allow you display all of the Car brands of a each Person instance, you can take a look at this example to get a grasp of Cell rendering, and here is my example that could help you in your case:

First set the type of the content of cells in vehicleBrandCol to ArrayList<String>:

private TableColumn<Person, ArrayList<Car>> vehicleBrandCol;

Then set the CellValueFactory as follows:

vehicleBrandCol.setCellValueFactory(new PropertyValueFactory<Person, ArrayList<Car>>("cars"));

and then you'll need custom cells to display data (Cars) contained within this ArrayList, so set the CellFactory as follows:

vehicleBrandCol.setCellFactory(column->{
            return new TableCell<Person, ArrayList<Car>>() {
                @Override
                protected void updateItem(ArrayList<Car> item, boolean empty) {
                    super.updateItem(item, empty);
                    if(item==null || empty) {
                        setGraphic(null);
                    } else {
                        VBox vbox = new VBox();
                        for(Car car : item) {
                            Label lbl = new Label(car.getBrand());
                            vbox.getChildren().add(lbl);
                        }
                        setGraphic(vbox);
                    }
                }
            };
        });

Notice that I'm creating a VBox and using Labels, you can use whatever Node you like, for example you can use a ListView, or a GridPane and set them as graphic for the Cell.

这篇关于JavaFX使用OneToMany关系填充表格视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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