要在JFX的表格中显示自定义的单元(TableCell), 必须实现一个继承于javafx.scene.control.TableCell的自定义单元. JFX官方没有为TableView提供像列表/选项按钮/文本框这样的常用控件, 如果你需要这些控件, 可以在另外一个项目中下载这些控件. 参见:http://www.javafxdata.org .(以下代码的实现参考了www.javafxdata.org)
首先定义一个TableCell来显示CheckBox.
/* CheckBoxTableCell.java 1.0 2010-2-2 * * Copyright (c) 2012 by Chen Zhiwu * All rights reserved. * * The copyright of this software is own by the authors. * You may not use, copy or modify this software, except * in accordance with the license agreement you entered into * with the copyright holders. For details see accompanying license * terms. */ public class CheckBoxTableCell<S, T> extends TableCell<S, T> { private final CheckBox checkBox; private final boolean showText; private final Callback<T, String> toString; private final Callback<Integer, ObservableValue<Boolean>> getSelectedProperty; private ObservableValue<Boolean> booleanProperty; public CheckBoxTableCell() { this(null, null); } public CheckBoxTableCell( Callback<Integer, ObservableValue<Boolean>> toString) { this(toString, null); } public CheckBoxTableCell( Callback<Integer, ObservableValue<Boolean>> getSelectedProperty, Callback<T, String> toString) { this.getSelectedProperty = getSelectedProperty; this.toString = toString; this.showText = toString != null; this.checkBox = new CheckBox(); setAlignment(Pos.CENTER); setGraphic(checkBox); if (showText) { checkBox.setAlignment(Pos.CENTER_LEFT); } } public CheckBoxTableCell( Callback<T, ObservableValue<Boolean>> callback, Callback<Integer, ObservableValue<Boolean>> getSelectedProperty, Callback<T, String> toString) { this.getSelectedProperty = getSelectedProperty; this.toString = toString; this.showText = toString != null; this.checkBox = new CheckBox(); setAlignment(Pos.CENTER); setGraphic(checkBox); if (showText) { checkBox.setAlignment(Pos.CENTER_LEFT); } } @Override protected void updateItem(T item, boolean empty) { super.updateItem(item, empty); if (empty) { setText(null); setGraphic(null); return; } if (this.showText) { setText(this.toString.call(item)); } setGraphic(this.checkBox); if (this.booleanProperty instanceof BooleanProperty) this.checkBox.selectedProperty().unbindBidirectional( (BooleanProperty) this.booleanProperty); ObservableValue localObservableValue = getSelectedProperty(); if (localObservableValue instanceof BooleanProperty) { this.booleanProperty = localObservableValue; this.checkBox.selectedProperty().bindBidirectional( (BooleanProperty) this.booleanProperty); } this.checkBox.visibleProperty().bind(getTableView().editableProperty() .and(getTableColumn().editableProperty()) .and(editableProperty())); }; private ObservableValue getSelectedProperty() { return ((this.getSelectedProperty != null) ? (ObservableValue) this.getSelectedProperty .call(Integer.valueOf(getIndex())) : getTableColumn() .getCellObservableValue(getIndex())); } }
CellFactory作为便利方法, 方便外部使用CheckBoxTableCell.
/* CellFactory.java 1.0 2010-2-2 * * Copyright (c) 2012 by Chen Zhiwu * All rights reserved. * * The copyright of this software is own by the authors. * You may not use, copy or modify this software, except * in accordance with the license agreement you entered into * with the copyright holders. For details see accompanying license * terms. */ public class CellFactory { ////// table check box public static <S> Callback<TableColumn<S, Boolean>, TableCell<S, Boolean>> tableCheckBoxColumn() { return tableCheckBoxColumn(null, null); } public static <S, T> Callback<TableColumn<S, T>, TableCell<S, T>> tableCheckBoxColumn( Callback<Integer, ObservableValue<Boolean>> paramCallback) { return tableCheckBoxColumn(paramCallback, null); } public static <S, T> Callback<TableColumn<S, T>, TableCell<S, T>> tableCheckBoxColumn( Callback<Integer, ObservableValue<Boolean>> paramCallback, boolean paramBoolean) { Callback<T, String> callback = new Callback<T, String>() { @Override public String call(T t) { return ((t == null) ? "" : t.toString()); } }; return tableCheckBoxColumn(paramCallback, callback); } public static <S, T> Callback<TableColumn<S, T>, TableCell<S, T>> tableCheckBoxColumn( final Callback<Integer, ObservableValue<Boolean>> getSelectedProperty, final Callback<T, String> toString) { return new Callback<TableColumn<S, T>, TableCell<S, T>>() { @Override public TableCell<S, T> call(TableColumn<S, T> paramTableColumn) { return new CheckBoxTableCell<S,T>(getSelectedProperty,toString); } }; } }
定义一个用于测试的实体类.
public class Goods{//商品类 private boolean available;//是否有效 用原子类型表示 private BooleanProperty hotSaleProperty;//是否热销 用可绑定属性表示 public boolean getAvailable(){ return avaliable; } public void setAvailable(boolean newValue){ this.available=newValue; } public boolean getHotSale(){ return hotSaleProperty.get(); } public boolean setHotSale(boolean newValue){ hotSaleProperty.set(newValue); } }
外部使用CheckBoxTableCell.
TableColumn<Goods, Boolean> availableColumn=new TableColumn<Goods, Boolean>("是否有效"); col.setCellValueFactory(new PropertyValueFactory<Goods,Boolean>("available"); col.setCellFactory(CellFactory.tableCheckBoxColumn(new Callback<Integer, ObservableValue<Boolean>>() { @Override public ObservableValue<Boolean> call(Integer index) { final Goods g= table.getItems().get(index); ObservableValue<Boolean> retval = new SimpleBooleanProperty(g,"available",g.getAvailable()); retval.addListener(new ChangeListener<Boolean>() { @Override public void changed( ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { g.setAvailable(newValue); } }); return retval; } })); TableColumn<Goods, Boolean> hotSaleColumn=new TableColumn<Goods, Boolean>("是否热销"); col.setCellValueFactory(new PropertyValueFactory<Goods,Boolean>("hotSale"); col.setCellFactory(CellFactory.tableCheckBoxColumn());
上面两个列使用不同的绑定方法. 第一列"是否有效"对应Goods中的boolean属性available. 该属性不支持JFX的动态绑定, 所以在定义列的时候建立一个Callback来动态更新属性.
第二个列"是否热销"对应Goods的boolean属性hotSaleProperty. 该属性支持JFX的动态绑定, 在定义列时无需做任何修改就可以实现实体与表格的绑定.
从上面的例子也可以看到, 在新版的JFX中, 如果实体类原生支持JFX的绑定类型在实现数据绑定会方便很多.
以上是JFX中自定义单选框的实现. 关于列表(ListView)和树(TreeView)的实现也类似.
参考阅读:
JFX的数据绑定:http://docs.oracle.com/javafx/2.0/binding/jfxpub-binding.htm
用于数据绑定的JFX框架: http://www.javafxdata.org