JavaFx TableView 实时的根据行对象数据变化刷新

1, 最简单粗暴,但也最不合理的做法
在数据对象更新后,调用 table.refresh() 方法。
这样做,表格实际上是刷新了,因为绑定的list里的对象确实发生了变化。
* 但是,这样并不符合数据绑定的工作方式,实际上调用refresh()的结果是重新渲染表格,可理解为表格初始化为空白后,重新加载了,当然实际fx不是这么做,但refresh()意味着实际是UI层重新初始化。
* 并不是数据绑定的监听起了作用。原因(痛点):table 绑定 list ,Oracle 只实现了增加、删除2个动作的监听,即是说,list 中单个元素本身属性值的修改,并不会被数据绑定所监听。
因为以上原因,出现的现象就是:
当 list 中元素有增、删时候, table 能够实时刷新。
当 list 中元素属性变化时候, table 不能实时刷新。(因为此时修改事件并不受监听,list 不认为自己有变化,随之 table 也就不会刷新)。
—- 第1种情况,致使 list 监听不到变化的前提是,修改的属性为JavaBean普通属性类型(如String,Integer) ,对 table cell 定义如:

tc_status.setCellValueFactory(new PropertyValueFactory<Account,String>("status"));

2,因为JavaBean普通属性,即使通过

new PropertyValueFactory<Account,String>("name")  

这样的包装,变成可以在 table 中显示,但实际上偏离了 JavaFx 的设计初衷。
与 JavaFx UI 层进行交互的类属性,应当定义为对应的 xxxProperty 包装类 (如 StringProperty , IntegerProperty 等 )。
然后,在对 table cellValueFactory 定义时,就可以直接返回 xxxProperty 对象 (因为 StringProperty 本身就是 ObservableValue 的子类)
代码实例:

    // 定义为 final 好像是一种规范做法
    private final StringProperty status = new SimpleStringProperty();

    // * 特别说明: xxxProperty 方法名,是 fx 的规范,只要属性名加上 Peoperty() 作为方法名,fx 就能自动监听该属性的变化!
    public StringProperty statusProperty() {
        return status;
    }
    // 原有的 set 方法,并不受字段类型变化而改变,仍然接受同样的参数,只是方法体需要修改一下
    public void setStatus(String status) {
        this.status.set(status);
    }


    // 原有的 get 方法,并不受字段类型变化而改变,仍然返回同样的类型,只是方法体需要修改一下
    public String getStatus(){
        return status.get();
    }   


    ....
    // Controller 中定义
    // 这样的写法就行了!当该属性值变化时,fx 绑定能立即捕捉到,并且刷新UI
    tc_status.setCellValueFactory(new PropertyValueFactory("status"));

经过这样对原来JavaBean属性的改造,当属性发生变化时,list 能够捕捉到,因此 table 上对应的值也能实时刷新。(这才是数据绑定,而不是第1种做法中对table UI层的强制刷新)

要注意,如果是 IntegerProperty , DoubleProperty 数字类型的,应定义为 Number ,而不是 Interger,如下所示,对应的 setCellValueFactory 方法对应参数类型也应为 Number。(* 非必须定义,可以不定义)

TableColumn<Account,Number> tc_num4xxx;

前面定义 setValueFactory 的方法,在 JDK8 中可以这样写:


tc_num4xxx.setCellValueFactory(param->param.getValue().num4xxx());

3, 高级做法:
table 上每个单元格,实际上不只可以容纳String、Integer 等类型,还可以容纳各种FX UI控件,
比如可以将单元格填充为 Label , CheckBox , ProgressBar

示例 (把 ProgressBar 塞进去)

        tc_progress.setCellValueFactory(
                new Callback<TableColumn.CellDataFeatures<Account, ProgressBar>, ObservableValue<ProgressBar>>() {
                    @Override
                    public ObservableValue<ProgressBar> call(
                            TableColumn.CellDataFeatures<Account, ProgressBar> param) {
                // 取出 table 上绑定的对应对象
                        Account account = param.getValue();
                // 制造 ProgressBar UI 实例
                        ProgressBar progressbar = new ProgressBar();
                // 绑定 progress这个property属性到UI上
                        progressbar.progressProperty().bind(account.progress());
                // 返回 ProgressBar 类型对象
                        return new SimpleObjectProperty<ProgressBar>(progressbar);
                    }
         });

如果要塞一个 Label 进去,同理参数类型设为 Label , 然后给想要单元格能够监听的属性 添加onChange监听,这样当属性变化时, Label 的 text 能够被更新,也就实现了刷新的目的。

tc_status.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Account,Label>, ObservableValue<Label>>(){

            @Override
            public ObservableValue<Label> call(CellDataFeatures<Account, Label> param) {
                // TODO 定义 Label 
                final Label label = new Label(param.getValue().getStatus());
                try {
                    label.setText(param.getValue().getStatus());

                    // 添加对属性值的监听事件,当值变化时,更新 Label 的 text 属性
                    param.getValue().status().addListener(new ChangeListener<String>() {
                        @Override
                        public void changed(ObservableValue<? extends String> observable, String oldValue,
                                String newValue) {
                            // TODO 
                            Platform.runLater(()->
                                label.setText("-->"+newValue)
                            );
                        }
                    });
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                return new SimpleObjectProperty<Label>(label);
            }
            /////////////////////////////////////////////////////
        });
  • 15
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值