问题描述
在使用javafx绘制PC桌面程序页面时,使用到了tableview,tableview可以很方便的维护一个可编辑的表,简易代码如下。
var bomList = observableListOf<BomContent.BomsInfo>()
tableview(bomList) {
column("客户名称", BomContent.BomsInfo::bomID) {
isEditable = true
prefWidth = 150.0
isSortable = true
}.makeEditable()
}
具体效果如下
这其中有一个方法.makeEditable()方法,其源码如下
inline fun <T, reified S : Any> TableColumn<T, S>.makeEditable() = apply {
tableView?.isEditable = true
isEditable = true
when (S::class.javaPrimitiveType ?: S::class) {
Int::class -> cellFactory = TextFieldTableCell.forTableColumn<T, S>(IntegerStringConverter() as StringConverter<S>)
Integer::class -> cellFactory = TextFieldTableCell.forTableColumn<T, S>(IntegerStringConverter() as StringConverter<S>)
Integer::class.javaPrimitiveType -> cellFactory = TextFieldTableCell.forTableColumn<T, S>(IntegerStringConverter() as StringConverter<S>)
Double::class -> cellFactory = TextFieldTableCell.forTableColumn<T, S>(DoubleStringConverter() as StringConverter<S>)
Double::class.javaPrimitiveType -> cellFactory = TextFieldTableCell.forTableColumn<T, S>(DoubleStringConverter() as StringConverter<S>)
Float::class -> cellFactory = TextFieldTableCell.forTableColumn<T, S>(FloatStringConverter() as StringConverter<S>)
Float::class.javaPrimitiveType -> cellFactory = TextFieldTableCell.forTableColumn<T, S>(FloatStringConverter() as StringConverter<S>)
Long::class -> cellFactory = TextFieldTableCell.forTableColumn<T, S>(LongStringConverter() as StringConverter<S>)
Long::class.javaPrimitiveType -> cellFactory = TextFieldTableCell.forTableColumn<T, S>(LongStringConverter() as StringConverter<S>)
Number::class -> cellFactory = TextFieldTableCell.forTableColumn<T, S>(NumberStringConverter() as StringConverter<S>)
BigDecimal::class -> cellFactory = TextFieldTableCell.forTableColumn<T, S>(BigDecimalStringConverter() as StringConverter<S>)
BigInteger::class -> cellFactory = TextFieldTableCell.forTableColumn<T, S>(BigIntegerStringConverter() as StringConverter<S>)
String::class -> cellFactory = TextFieldTableCell.forTableColumn<T, S>(DefaultStringConverter() as StringConverter<S>)
LocalDate::class -> cellFactory = TextFieldTableCell.forTableColumn<T, S>(LocalDateStringConverter() as StringConverter<S>)
LocalTime::class -> cellFactory = TextFieldTableCell.forTableColumn<T, S>(LocalTimeStringConverter() as StringConverter<S>)
LocalDateTime::class -> cellFactory = TextFieldTableCell.forTableColumn<T, S>(LocalDateTimeStringConverter() as StringConverter<S>)
Boolean::class.javaPrimitiveType -> {
(this as TableColumn<T, Boolean?>).useCheckbox(true)
}
else -> throw RuntimeException("makeEditable() is not implemented for specified class type:" + S::class.qualifiedName)
}
}
简而言之,就是无论我们使用到的类型为什么类型,该方法都会使表格该列可进行编辑,并适配对应类型,这在平时使用是没有问题的。但是如果是在view的root初始化时,tableview中创建的列数太多,且每一列都是调用的.makeEditable()方法,该view的root在调用invoke方法时就会报错Method too large。
解决方案
不使用column自带的方法.makeEditable(),根据使用的类型,进行单个编写,如下。
var bomList = observableListOf<BomContent.BomsInfo>()
tableview(bomList) {
column("客户名称", BomContent.BomsInfo::bomID) {
isEditable = true
prefWidth = 150.0
isSortable = true
cellFactory = TextFieldTableCell.forTableColumn<BomContent.BomsInfo, String>(DefaultStringConverter() as StringConverter<String>)
}
}
这里我们bomID使用到的是String类型。