Kotlin编写JavaFX的顺滑之数据控件(二)表视图TableView基础深入浅出
目录
并不神秘的Callback<P, R>
书接上回,简单几步,就能把一个对象列表显示为一个表格(每个对象一行,指定的属性为一列)。
- 定义行对应的数据结构,构成一个被观察的列表。
- 定义所有要显示的列,并逐一添加到表视图,添加顺序为从左往右的显示顺序。
- 将数据集合赋予给表视图的项集合。
- 将表视图实例添加用户界面容器中。
- 构造变更数据集合的用户界面和功能对表格进行操作。
这中间最为重要的就是构造列。
列的构造
val nameColumn= TableColumn<Person, String>("Name").apply {
cellValueFactory = PropertyValueFactory<Person, String>("name")
}
列对象有两个类型参数,第一个是行所对应的数据结构,这个类型与表视图的类型参数相同,第二个是当前列对应的属性的类型。
JavaFX的文档是这么说的:
TableColumn<S, T>
Type parameters:
<S> – The type of the TableView generic type (i.e. S == TableView<S>)
<T> – The type of the content in all cells in this TableColumn.
这里利用Kotlin的扩展函数apply
,设置了一个参数cellValueFactory
,这个参数的类型很有意思:
public class PropertyValueFactory<S,T> implements Callback<CellDataFeatures<S,T>, ObservableValue<T>>
{
// ...
}
Callback
接口
Callback
接口是Java语言早期的典型特色,因为那时候没有lambda语法,函数化编程还没有开始在Java中实现。
@FunctionalInterface
public interface Callback<P,R> {
/**
* The <code>call</code> method is called when required, and is given a
* single argument of type P, with a requirement that an object of type R
* is returned.
*
* @param param The single argument upon which the returned value should be
* determined.
* @return An object of type R that may be determined based on the provided
* parameter value.
*/
public R call(P param);
}
这个其实就定义了一个可以被调用的函数:其参数和返回值对应于接口的两个类型参数P
和R
。
回到cellValueFactory
我们知道,Kotlin对Java还做了一个属性访问的语法糖,也就是setXXXX
和getXXXX
可以简单的用xXXXX
的形式访问。
当setXXXX
方法可以访问(有定义并且可见),是一个可写属性,也就是属性可以作为左值(放在等号的左边);当只有getXXXX
方法时,是一个只读属性,不能作为左值。
这里的
cellValueFactory = PropertyValueFactory<Person, String>("name")
实际就是调用函数setCellValueFactory
,参数就是右边的这个Callback
的子类。
那么很简单,我们可以自己调用这个函数,并利用Kotlin的语法糖,写成:
setCellValueFactory {
SimpleStringProperty(it.value.name)
}
这就很简洁很强大了。
这里的it
的类型为:TableColumn.CellDataFeatures<Person, String>
,这个内部类的value
属性范围当前行对应的对象。返回值(也就是call
函数的返回值为ObservableValue<T>
。
只要符合这个输出就很好。
更加灵活的表视图
有了前面对源码深入浅出的简单分析和Kotlin语法糖的使用,我们可以很容易实现一些稍微复杂的、更加灵活的表视图产生方式。
替代MapValueFactory<T>
JavaFX还帮我们实现了一个更加灵活的对象表达方式,就是将每一行用一个字典类Map
来表达的形式。
使用这个很简单,但是我们也可以不用。
setCellValueFactory {
SimpleStringProperty(it.value.get("name"))
}
做数据处理和检查
在这个函数里面,就能够对数据进行检查,并做一些处理。
setCellValueFactory { cellData ->
var name = cellData.value.name
if (name[0].isLowerCase()) {
name = name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
}
SimpleStringProperty(name)
}
虚拟列
如此,对于已经定义好的Person
类,也很容易增加虚拟的列。不再赘述。
结论
利用表视图来展示一系列数据时,表视图获取某行某列的值利用一个函数接口。采用Kotlin的语法糖,很容易增加灵活的返回值的方式。
只能说吧, Java(pre 8)虽好,Kotlin更强大。