如何在JavaFX中实现独立单元? [英] How to implement independent cells in JavaFX?

查看:70
本文介绍了如何在JavaFX中实现独立单元?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力实现与剧院,电影院等席位选择类似的东西以及他们的不同意见。

I am trying to implement something similar to the choice of seats in a Theatre, Cinema, etc and their disponibility.

使用此代码:

int[] rowsColumns = getRowsNColumns(); // [0] = rows : [1] = columns
TableColumn [] tableColumns = new TableColumn[rowsColumns[1]];
Callback<TableColumn, TableCell> cellFactory =
        new Callback<TableColumn, TableCell>() {
            @Override
            public TableCell call(TableColumn p) {
                TableCell<MyObject,Boolean> cell = new DisponibilityCell();
                cell.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler());
                 return cell;
            }
        };
 for (int i = 0; i < rowsColumns[1]; i++) {
    tableColumns[i] = new TableColumn<MyObject, Boolean>(String.valueOf(i+1));
    tableColumns[i].setPrefWidth((table.getPrefWidth()-15)/rowsColumns[1]);
    tableColumns[i].setCellValueFactory(new PropertyValueFactory<MyObject, Boolean>("disponibility"));
    tableColumns[i].setCellFactory(cellFactory);
    tableColumns[i].setSortable(false);
}
table.getColumns().addAll(tableColumns);
List<MyObject> list = new ArrayList<>();
for (int i = 0; i < rowsColumns[0]; i++) {
    list.add(new MyObject(i,true));
}
table.getItems().addAll(list);
table.getSelectionModel().setCellSelectionEnabled(true);

我能够得到这个,这是我想要的直观(没有样式)。

I am able to get this, which is quite what I want visually (without styles).

问题是它实际上是为第一列生成行,而另一个只是值的副本。

The problem is that it actually is generating the rows for the first column, and the other is just a copy of the values.

我想我理解这一点,但不知道如何实际解决。如果我理解正确,它会考虑每一行的对象,并在所有列中显示对象属性( disponibility ),因为它们都使用相同的get。

I think I understand this in theory, but do not know how to actually solve. If I understand correctly, it is considering an object for each row, and displaying the object property (disponibility) in all columns as all of them use the same get.

我希望每个对象都由一个单元格表示,而不是一行。
来自所有行的所有单元格都获得相同的属性,即座位的 disponibility ,但每个单元格应该是一个独立的对象。

I want that each object is represented by a cell, not a row. All cells from all rows get the same property, the disponibility of the seat, however each cell should be an independent object.

推荐答案

具有 TableView 的工作解决方案可能是:

A working solution with a TableView could be this:

首先,我们需要在 MyObject 中保存给定行的每一列的信息。为此,我们使用 ObservableList 以及列的所有布尔属性:

First of all we need to hold in MyObject the information for a each and every column of a given row. For that we use an ObservableList with all the boolean properties for the columns:

class MyObject {

    public MyObject(int tam, boolean disponibility){
        cols = FXCollections.observableArrayList();
        IntStream.range(0, tam).boxed()
             .forEach(i->cols.add(new SimpleBooleanProperty(disponibility)));
    }

    private final ObservableList<BooleanProperty> cols;

    public void setColDisponibility(int col, boolean disponibility){
        cols.get(col).set(disponibility);
    }

    public boolean getColDisponibility(int col){
        return cols.get(col).get();
    }

    public BooleanProperty colDisponibilityProperty(int col){
        return cols.get(col);
    }
}

现在我们将定义我们的自定义单元 DisponibilityCell ,基于 CheckBox 以简化。此框上的监听器将通过调用 setColDisponibility()来帮助我们保持模型同步。

Now we will define our custom cell DisponibilityCell, based on a CheckBox for simplicity. A listener on this box will helps us keep in sync our model, by calling setColDisponibility().

class DisponibilityCell extends TableCell<MyObject, Boolean> {
    private final CheckBox box = new CheckBox();

    public DisponibilityCell(int col){
        box.setOnAction(e -> {
            getTableView().getItems().get(getIndex()).setColDisponibility(col, box.isSelected());
        });
    }

    @Override
    protected void updateItem(Boolean item, boolean empty) {
        super.updateItem(item, empty);

        if(item!=null && !empty){
            box.setSelected(item);
            setGraphic(box);
        }
        else {
            setText(null);
            setGraphic(null);
        }
    }
}

最后,我们可以创建表。首先,我们提供所有数据,设置为每个单元格为真。然后我们创建列。对于每一列,我们设置其 id 以跟踪列数。我们提供基于 colDisponibilityProperty(int col)属性的单元格值工厂,以及基于 DisponibilityCell 的单元工厂。

Finally, we can create the table. First, we provide all the data, setting to true every cell. Then we create the columns. For every column, we set its id to keep track of the number of column. We provide the cell value factory based on colDisponibilityProperty(int col) property, and the cell factory, based on a DisponibilityCell.

@Override
public void start(Stage primaryStage) {

    TableView<MyObject> table = new TableView<>();
    table.setPrefSize(800, 600);

    int[] rowsColumns = new int[]{10,20}; // [0] = rows : [1] = columns
    ObservableList<MyObject> list = FXCollections.observableArrayList();
    for (int i = 0; i < rowsColumns[0]; i++) {
        list.add(new MyObject(rowsColumns[1],true));
    }

    List<TableColumn<MyObject,Boolean>> tableColumns = new ArrayList<>(rowsColumns[1]);
    IntStream.range(0, rowsColumns[1]).boxed().forEach(i-> {
        TableColumn<MyObject,Boolean> tableColumn = new TableColumn<>(String.valueOf(i+1));
        tableColumn.setId(String.valueOf(i));
        tableColumn.setPrefWidth((table.getPrefWidth()-15)/rowsColumns[1]);
        tableColumn.setCellValueFactory(param -> {
            int col=Integer.parseInt(param.getTableColumn().getId());
            return param.getValue().colDisponibilityProperty(col);
        });
        tableColumn.setCellFactory(param -> 
             new DisponibilityCell(Integer.parseInt(param.getId())));
        tableColumn.setSortable(false);
        tableColumns.add(tableColumn);
    });
    table.getColumns().addAll(tableColumns);

    table.getItems().addAll(list);
    table.getSelectionModel().setCellSelectionEnabled(true);
    table.setEditable(true);

    Scene scene = new Scene(table, 800, 600);

    primaryStage.setScene(scene);
    primaryStage.show();

}

请注意,您可以随时访问更新的模型。例如,您可以根据某个按钮点击打印它:

Note that you can access to your updated model at any time. For instance, you can print it based on some button click:

button.setOnMouseClicked(e->{
        table.getItems().forEach(r->{
            IntStream.range(0, rowsColumns[1]).boxed()
                    .forEach(i->System.out.print(" "+(r.getColDisponibility(i)?1:0)));
            System.out.println("");
        });
    });

这篇关于如何在JavaFX中实现独立单元?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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