JavaFx TableView 实时的根据行对象数据变化刷新
2017-03-30 05:47
1711 查看
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 定义如:
2,因为JavaBean普通属性,即使通过
这样的包装,变成可以在 table 中显示,但实际上偏离了 JavaFx 的设计初衷。
与 JavaFx UI 层进行交互的类属性,应当定义为对应的 xxxProperty 包装类 (如 StringProperty , IntegerProperty 等 )。
然后,在对 table cellValueFactory 定义时,就可以直接返回 xxxProperty 对象 (因为 StringProperty 本身就是 ObservableValue 的子类)
代码实例:
经过这样对原来JavaBean属性的改造,当属性发生变化时,list 能够捕捉到,因此 table 上对应的值也能实时刷新。(这才是数据绑定,而不是第1种做法中对table UI层的强制刷新)
要注意,如果是 IntegerProperty , DoubleProperty 数字类型的,应定义为 Number ,而不是 Interger,如下所示,对应的 setCellValueFactory 方法对应参数类型也应为 Number。(* 非必须定义,可以不定义)
前面定义 setValueFactory 的方法,在 JDK8 中可以这样写:
3, 高级做法:
table 上每个单元格,实际上不只可以容纳String、Integer 等类型,还可以容纳各种FX UI控件,
比如可以将单元格填充为 Label , CheckBox , ProgressBar
示例 (把 ProgressBar 塞进去)
如果要塞一个 Label 进去,同理参数类型设为 Label , 然后给想要单元格能够监听的属性 添加onChange监听,这样当属性变化时, Label 的 text 能够被更新,也就实现了刷新的目的。
在数据对象更新后,调用 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); } ///////////////////////////////////////////////////// });
相关文章推荐
- javaFX 在for循环中执行代码,使tableview单行依次实时刷新更新数据的解决方案
- 关于tableview的界面得数据的变化怎么进行刷新的问题
- JavaFX8 -- TableView中TableCell对象管理的奇怪问题-多次异步刷新单元格慎重!
- ios tableView那些事 (十八) UITableView单行刷新数据
- (四 )Knockout - ViewModel 的使用3 - 对象属性变化的实时更新
- Android ViewPager刷新Fragment数据(ViewPager获取Fragment对象)
- oracle 学习笔记(十一) 数据库常用对象, table ,constraint ,index ,view和数据字典
- iOS之TableView左划删除与刷新单挑数据
- iOS tableView刷新选中cell数据
- IOS - TableView上拉刷新数据后设置显示偏移(新数据置顶)
- IOS tableView的数据刷新
- tableView 重载数据/ 刷新cell (代码)
- tableView - 数据刷新
- (十九)TableView的点击监听和数据刷新(Alert的多种样式) -tag传值的技巧
- iOS—TableView的点击监听和数据刷新(Alert的多种样式) -tag传值的技巧
- javafx基于使用fxml布局的tableview数据绑定用法
- ios-day13-01(私人通讯录。控制器之间的数据传递、保存密码和自动登录的实现、普通对象的归档、UITableView的局部刷新和向左滑动删除功能等等)
- iOS 刷新tableView的某一行的row的时候,row的高度增加,数据也增加。
- javaFxTableView可编辑表格,当我添加一个TextFieldTableCell至TableColumn的CellFactory中后,在编辑数据时后台报错
- 点不同的按钮刷新tableview的时间切换数据