是否可以在JavaFX8中逐行禁用可编辑表列? [英] Is it possible to disable editable table columns on a row basis in JavaFX8?

查看:458
本文介绍了是否可以在JavaFX8中逐行禁用可编辑表列?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用例,我认为这是相当标准的,但是我无法找到有关如何执行此操作的示例,或者是否有可能.

I have a use case which I would assume is pretty standard, however I haven't been able to find an example on exactly how to do this, or if it's possible.

假设我具有以下TableView

Let's assume I have the following TableView

First Name    Last Name    Street    NewRecord

Tom           Smith        Main St.     Yes
Mike          Smith        First St.    No

在这种情况下,由于记录是新记录,因此网格中的前三个单元格应该是可编辑的,但是,如果记录不是新记录,则应该禁用姓氏"单元格.

In this case, the grid should have the first three cells editable since the record is new, however when the record is not new then the Last Name cell should be disabled.

我在CellFactory和RowFactory中进行了尝试-但是还没有找到实现此目的的方法.

I tried this in the CellFactory and RowFactory - but haven't seen a way to accomplish this.

感谢您的帮助.

推荐答案

最简单的方法是使用第三方绑定库:ReactFX 2.0内置了此功能,如

The easiest way to do this is with a third-party binding library: ReactFX 2.0 has this functionality built-in, as described here. Using that you can do

TableColumn<Person, String> lastNameColumn = new TableColumn<>("Last Name");
lastNameColumn.setEditable(true);
lastNameColumn.setCellFactory(tc -> {
    TableCell<Person, String> cell = new TextFieldTableCell<>();
    cell.editableProperty().bind(
        // horrible cast needed because TableCell.tableRowProperty inexplicably returns a raw type:
        Val.flatMap(cell.tableRowProperty(), row -> (ObservableValue<Person>)row.itemProperty())
           .flatMap(Person::newRecordProperty)
           .orElseConst(false));
    return cell ;
});

(假定Person表模型对象具有明显的JavaFX属性和方法).

(assumes a Person table model object with the obvious JavaFX properties and methods).

没有该库,您需要一个非常痛苦的嵌套侦听器列表:

Without the library, you need a pretty miserable nested list of listeners:

TableColumn<Person, String> lastNameColumn = new TableColumn<>("Last Name");
lastNameColumn.setEditable(true);
lastNameColumn.setCellFactory(tc -> {
    TableCell<Person, String> cell = new TextFieldTableCell<>();
    ChangeListener<Boolean> newRecordListener = (obs, wasNewRecord, isNewRecord) -> updateEditability(cell);
    ChangeListener<Person> rowItemListener = (obs, oldPerson, newPerson) -> {
        if (oldPerson != null) {
            oldPerson.newRecordProperty().removeListener(newRecordListener);
        }
        if (newPerson != null) {
            newPerson.newRecordProperty().addListener(newRecordListener);
        }
        updateEditability(cell);
    };
    ChangeListener<TableRow> rowListener = (obs, oldRow, newRow) -> {
        if (oldRow != null) {
            ((ObservableValue<Person>)oldRow.itemProperty()).removeListener(rowItemListener);
            if (oldRow.getItem() != null) {
                ((Person)oldRow.getItem()).newRecordProperty().removeListener(newRecordListener);
            }
        }
        if (newRow != null) {
            ((ObservableValue<Person>)newRow.itemProperty()).addListener(rowItemListener);
            if (newRow.getItem() != null) {
                ((Person)newRow.getItem()).newRecordProperty().addListener(newRecordListener);
            }
        }
        updateEditability(cell);
    };
    cell.tableRowProperty().addListener(rowListener);
    return cell ;
});

然后

private void updateEditability(TableCell<Person, String> cell) {
    if (cell.getTableRow() == null) {
        cell.setEditable(false);
    } else {
        TableRow<Person> row = (TableRow<Person>) cell.getTableRow();
        if (row.getItem() == null) {
            cell.setEditable(false);
        } else {
            cell.setEditable(row.getItem().isNewRecord());
        }
    }
}

使用旧式" API的替代方法是

An alternative using a "legacy style" API is

TableColumn<Person, String> lastNameColumn = new TableColumn<>("Last Name");
lastNameColumn.setEditable(true);
lastNameColumn.setCellFactory(tc -> {
    TableCell<Person, String> cell = new TextFieldTableCell<>();
    cell.editableProperty().bind(
        Bindings.selectBoolean(cell.tableRowProperty(), "item", "newRecord"));
    return cell ;
});

我不喜欢这个选项,因为它没有任何类型安全性(或者根本没有任何编译器检查),此外,在某些早期版本的JavaFX中,如果链"中的任何属性为null,都会生成几乎无穷的警告消息.值(在这种情况下,经常会使用这些值).我相信后一个问题已解决,但是ReactFX的版本要好得多,恕我直言.

I dislike this option, because it lacks any type safety (or indeed any compiler checks at all), and additionally in some earlier versions of JavaFX would generate almost endless warning messages if any of the properties in the "chain" had null values (which they will, frequently, in this case). I believe the latter issue is fixed, but the ReactFX version of this is far better, imho.

这篇关于是否可以在JavaFX8中逐行禁用可编辑表列?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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