今天用javafx写客户端时,需要在TableView控件中插入CheckBox列,并且在点击CheckBox时获取点击行的信息并显示在右边的ListView中,如图所示。
在网上查找了一下,一般都是建立一个TableColumn<StockVO,Boolean>加入TableView然后调用setCellFactory()对CheckBox列下的每一个cell进行初始化、点击监听。但在实际操作中发现一个问题,就是当数据过多时勾选某些列,将滚动条向下拉再回拉时CheckBox又会重新填充,已经勾选过的CheckBox又会取消勾选,原因是CellFactory中的updateItem()函数会被再次运行,所以勾选会消失。
于是我新建了一个数据类,在数据类中添加了一个boolean类型变量:
public class CustomVO {
private StringProperty code;
private StringProperty name;
private BooleanProperty chosen;
public CustomVO(StockVO vo,boolean chosen){
this.code = new SimpleStringProperty(vo.getCode());
this.name = new SimpleStringProperty(vo.getName());
this.chosen = new SimpleBooleanProperty(chosen);
}
public StringProperty getCodeProperty(){
return code;
}
public StringProperty getNameProperty(){
return name;
}
public BooleanProperty getChosenProperty(){
return chosen;
}
public void setChosen(boolean chosen){
this.chosen = new SimpleBooleanProperty(chosen);
}
}
接着我们在controller类里面声明表格的类型:
@FXML private TableView<CustomVO> tableview;
@FXML private TableColumn<CustomVO,String> code;
@FXML private TableColumn<CustomVO,String> name;
@FXML private TableColumn<CustomVO,Boolean> chosen;
接着绑定数据:
@FXML
/**
* 初始化
*/
private void initialize() {
ObservableList list = FXCollections.observableArrayList(arraylist);
tableview.setItems(list);
code.setCellValueFactory(cellData -> cellData.getValue().CodeProperty());
name.setCellValueFactory(cellData -> cellData.getValue().getNameProperty());
chosen.setCellValueFactory(cellData->cellData.getValue().ChosenProperty());
chosen.setCellFactory(new Callback<TableColumn<CustomVO,Boolean>, TableCell<CustomVO,Boolean>>() {
@Override
public TableCell<CustomVO,Boolean> call(TableColumn<CustomVO,Boolean> p) {
return new TableCell<CustomVO,Boolean>(){
final CheckBox cell = new CheckBox();
{setAlignment(Pos.CENTER);}
{cell.setOnAction(
new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent t) {
CustomVO vo = getTableView().getItems().get(getIndex());
if (vo.getChosen()==false) {
StockVO stock = new StockVO();
stock.setName(vo.getName());
po.setCode(vo.getCode());
cell.setSelected(true);
vo.setChosen(true);
} else {
cell.setSelected(false);
vo.setChosen(false);
String Name = vo.getName();
Iterator<StockVO> iterator = codelist.iterator();
while (iterator.hasNext()) {
if (iterator.next().getName().equals(Name)) {
iterator.remove();
}
}
}
}});}
@Override
public void updateItem(Boolean item, boolean empty) {
super.updateItem(item, empty);
if(!empty){
CustomVO vo = getTableView().getItems().get(getIndex());
String Name = vo.getName();
Iterator<StockVO> iterator = codelist.iterator();
if(item==false){
cell.setSelected(false);
while (iterator.hasNext()) {
if (iterator.next().getName().equals(Name)) {
iterator.remove();
}
}
}
else{
cell.setSelected(true);
boolean isExist = false;
for(int m=0;m<codelist.size();m++){
if(codelist.get(m).getName().equals(Name))
isExist = true;
}
if(isExist == false){
StockPO po = new StockPO();
po.setCode(vo.getCode());
po.setName(vo.getName());
StockVO stock = new StockVO(po);
codelist.add(stock);
}
}
setGraphic(cell);
}
}
};
}
});
这样就可以在TableView中添加CheckBox列了。