【问题标题】:Rendering a check box with a cellFactory in TableView doesn't work as it should在 TableView 中使用 cellFactory 渲染复选框无法正常工作
【发布时间】:2016-01-20 19:24:38
【问题描述】:

当用户单击表格视图上的复选框时,我想为折线图系列创建以下功能。项目的表视图具有图表系列的 ObservableList。所以控制器中的以下代码。

控制器类从 fxml 文件中注入以下内容。

@FXML
public TableView<Series<Number, Number>> tableViewStatisticsOverview;

@FXML
public TableColumn<Series<Number, Number>, String> tableColumnStatisticName;

@FXML
public TableColumn<Series<Number, Number>, Series<Number, Number>> tableColumnShowSeries;

@FXML
public TableColumn<Series<Number, Number>, Series<Number, Number>> tableColumnAction;

//later on the code
tableViewStatisticsOverview.setItems(chart.getData()); // chart is a linexy chart

//setting up the tableColumnShowSeries to show a checkbox and show and hide the series


tableColumnShowSeries.setCellValueFactory(
            new Callback<TableColumn.CellDataFeatures<Series<Number, Number>, Series<Number, Number>>, ObservableValue<Series<Number, Number>>>() {

                @Override
                public ObservableValue<Series<Number, Number>> call(CellDataFeatures<Series<Number, Number>, Series<Number, Number>> param) {
                    return new ReadOnlyObjectWrapper<Series<Number, Number>>(param
                            .getValue());
                }
            });

tableColumnShowSeries.setCellFactory(
        new TableCollumnCellWithCheckBoxFactoryWrapper());

作为表格的数据,我将整个系列设置在表格的行上,以便能够根据复选框的值设置系列的节点是否可见

TableCollumnCellWithCheckBoxFactoryWrapper 类

package com.nokia.avalanche.client.util.fxhelper;

import javafx.scene.chart.XYChart.Series;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.util.Callback;

public class TableCollumnCellWithCheckBoxFactoryWrapper implements
    Callback<TableColumn<Series<Number, Number>, Series<Number, Number>>, TableCell<Series<Number, Number>, Series<Number, Number>>> {


@Override
public TableCell<Series<Number, Number>, Series<Number, Number>> call(TableColumn<Series<Number, Number>, Series<Number, Number>> param) {
        return new CheckBoxCell();
    }

}

CheckBoxCell 类

public class CheckBoxCell
    extends TableCell<Series<Number, Number>, Series<Number, Number>> {

Logger LOG = LogManager.getLogger(CheckBoxCell.class);

private HBox checkBoxContainer;
private CheckBox checkBoxShow;

public CheckBoxCell() {
    checkBoxContainer = new HBox();
    checkBoxShow = new CheckBox("");
    checkBoxContainer.setAlignment(Pos.CENTER);
    checkBoxShow.setSelected(true);
    checkBoxContainer.getChildren().add(checkBoxShow);

}



private void addListenerOnCheckBox(Series<Number, Number> series) {

      checkBoxShow.setOnAction(new EventHandler<ActionEvent>() {

          @Override
          public void handle(ActionEvent arg0) {
              LOG.debug("Show checkbox selected: "
                    + checkBoxShow.isSelected());              
              series.getNode().setVisible(checkBoxShow.isSelected());
              if (series.getNode().isVisible()) {
                  series.getNode().toFront();
                  for (Data<Number, Number> data : series.getData()) {
                      data.getNode().toFront();
                  }
              } else {
                  series.getNode().toBack();
                  for (Data<Number, Number> data : series.getData()) {
                      data.getNode().toBack();
                  }
              }          
          }
      });


    }

    @Override
    protected void updateItem(Series<Number, Number> series, boolean empty) {
        super.updateItem(series, empty);
        if (!empty && series != null) {

            addListenerOnCheckBox(series);

            LOG.debug("Series is not empty");
            LOG.debug("Updating item for series with name: " + series.getName());
            setGraphic(checkBoxContainer);
        } else {
            LOG.debug("Series is empty");
            setGraphic(null);
        }

    }

}

问题是,在图表上添加了一些系列并显示在表格上并尝试单击复选框后,另一个复选框的行为与我单击的那个相同,即它的状态从已选中根据我点击的第一个取消选中。调试表明,当代码从动作处理程序进入句柄方法时,复选框是同一个对象,因此取消选中一个会使另一个未选中。我错过了什么吗?还有其他方法可以使用复选框并捕捉复选框状态的变化吗?

【问题讨论】:

    标签: checkbox tableview javafx-8 custom-cell


    【解决方案1】:

    我可以看到两件事:

    1. 您应该在复选框上设置一次侦听器,从 构造函数。使用getItem() 获取当前系列 由单元格显示。
    2. updateItem 中,您需要更新复选框以匹配是否显示该系列的状态。

    所以我认为:

    public class CheckBoxCell
        extends TableCell<Series<Number, Number>, Series<Number, Number>> {
    
    Logger LOG = LogManager.getLogger(CheckBoxCell.class);
    
    private HBox checkBoxContainer;
    private CheckBox checkBoxShow;
    
    public CheckBoxCell() {
        checkBoxContainer = new HBox();
        checkBoxShow = new CheckBox("");
        checkBoxContainer.setAlignment(Pos.CENTER);
        checkBoxShow.setSelected(true);
        checkBoxContainer.getChildren().add(checkBoxShow);
        addListenerOnCheckBox();
    }
    
    
    
    private void addListenerOnCheckBox() {
    
          checkBoxShow.setOnAction(new EventHandler<ActionEvent>() {
    
              @Override
              public void handle(ActionEvent arg0) {
    
                  Series<Number, Number> series = getItem();
    
                  if (series == null)  {
                      return ;
                  }
    
                  LOG.debug("Show checkbox selected: "
                        + checkBoxShow.isSelected());              
                  series.getNode().setVisible(checkBoxShow.isSelected());
                  if (series.getNode().isVisible()) {
                      series.getNode().toFront();
                      for (Data<Number, Number> data : series.getData()) {
                          data.getNode().toFront();
                      }
                  } else {
                      series.getNode().toBack();
                      for (Data<Number, Number> data : series.getData()) {
                          data.getNode().toBack();
                      }
                  }          
              }
          });
    
    
        }
    
        @Override
        protected void updateItem(Series<Number, Number> series, boolean empty) {
            super.updateItem(series, empty);
            if (!empty && series != null) {
    
                checkBoxShow.setSelected(series.getNode().isVisible());
    
                LOG.debug("Series is not empty");
                LOG.debug("Updating item for series with name: " + series.getName());
                setGraphic(checkBoxContainer);
            } else {
                LOG.debug("Series is empty");
                setGraphic(null);
            }
    
        }
    
    }
    

    未测试,所以我可能遗漏了其他东西......

    【讨论】:

    • 谢谢不知道获取项目...是的,当我在没有显示/隐藏代码 sn-p 的情况下测试它并在我认为它有效时添加侦听器时......所以我需要如何获取不输入更新项的单元格系列
    猜你喜欢
    • 2015-08-26
    • 1970-01-01
    • 2017-04-04
    • 1970-01-01
    • 1970-01-01
    • 2020-07-31
    • 2021-05-04
    • 2018-07-30
    相关资源
    最近更新 更多