【问题标题】:Javafx2.2: Checkboxes in table view mess up when table is scrolledJavafx2.2:滚动表格时表格视图中的复选框混乱
【发布时间】:2014-11-19 03:05:52
【问题描述】:

使用表格视图附带的垂直滚动条时会出现此问题。这是我的表格视图的样子:

http://i.stack.imgur.com/w7Wv3.png

当您使用鼠标滚轮滚动时,这很好。当您使用滚动条上的向上/向下箭头滚动时,这很好。但是,当您实际使用鼠标指针拖动滚动条时,复选框中的选择就会变得混乱。例如,如果您看到上面链接的图像,则选择了第三个复选框。滚动后,现在可能会选中第 5 个复选框或第 2 个复选框。甚至可能会选择另外两个复选框。

我认为这是表格视图滚动条的刷新/重绘问题。

解决这个问题的正确方法是拦截垂直滚动事件并在用户滚动时手动刷新网格。为此,我需要能够掌握表格滚动条的句柄。像 table.getScrollBar().setEventHandler(this) 这样的东西。我无法做到这一点。表格的滚动条似乎被隐藏了。如果无法到达滚动条,则无法拦截滚动事件,也无法修复此问题。

这是我的 fxml 的样子:

<TableView fx:id="table" prefWidth="650" prefHeight="200" AnchorPane.topAnchor="50" AnchorPane.leftAnchor="0">
<columns>
    <TableColumn fx:id="nameCol" text="Product Type" prefWidth="125" />
    <TableColumn fx:id="totalCol" text="Total" prefWidth="65" />
    <TableColumn fx:id="entitledCol" text="Entitled"  />
    <TableColumn fx:id="forPurchaseCol" text="For Purchase" prefWidth="125" />
    <TableColumn fx:id="nonImmediate" text="Non Immediate" prefWidth="125" />
</columns>              
</TableView>

这是来自控制器的相关java代码:

nameCol.setCellValueFactory(new PropertyValueFactory<Product, String>("productFullName"));
totalCol.setCellValueFactory(new PropertyValueFactory<Product, Integer>("totalCount"));
entitledCol.setCellValueFactory(new PropertyValueFactory<Product, Integer>("entitledImmediateCount"));
forPurchaseCol.setCellValueFactory(new PropertyValueFactory<Product, ObservableMap<String, Number>>(
                                                                                                      "forPurchaseImmediateCountAndPrice"));
nonImmediate.setCellValueFactory(new PropertyValueFactory<Product, Integer>("nonImmediateCount"));
forPurchaseCol.setCellFactory(new Callback<TableColumn<Product, ObservableMap<String, Number>>, TableCell<Product, ObservableMap<String, Number>>>() {
    @Override
    public TableCell<Product, ObservableMap<String, Number>> call(TableColumn<Product, ObservableMap<String, Number>> col) {
        return new PriceCell();
    }
});

这就是 PriceCell.java 的样子:

public class PriceCell extends TableCell<Product, ObservableMap<String, Number>> {
private CheckBox box = new CheckBox();

@Override
protected void updateItem(ObservableMap<String, Number> countPrice, boolean empty) {
    super.updateItem(countPrice, empty);

    if(countPrice != null) {
        int count = (Integer) countPrice.get("count");
        if(count == 0) {
            setText("0");
        }
        else {
            setText(countPrice.get("count") + " ($" + countPrice.get("price") + ")");
            box.setOnAction(this);
            box.setId(countPrice.get("price").toString());
            setGraphic(box);
        }
    }
    else {
        setText("");
        setGraphic(null);
    }
}
}

谢谢。任何帮助表示赞赏。

【问题讨论】:

    标签: checkbox javafx scroll tableview


    【解决方案1】:

    不知何故,您的模型没有很好地连接...

    PriceCell 试图在一列中混合两种不同的内容:复选框的布尔值,在呈现单元格时不会存储或处理其状态,has no field inProduct` 和字符串,这与检查状态无关。所以当用户点击检查时,标签不会受到影响。

    虽然渲染看起来正确,但当您使用鼠标滚动时,复选框状态会丢失,并且没有回调可以正确找到它。

    已经有一个带有复选框的 TableCell 实现:CheckBoxTableCell。但它只需要Boolean 作为参数,因为它只需要知道状态(选择与否)。您可以为标签添加一些StringConverter,但这仅与选定状态有关。

    要解决这个问题,我的建议是:

    首先,在Product中新建一个字段:

    private final BooleanProperty purchase = new SimpleBooleanProperty();
    
    public boolean isPurchase() {
        return purchase.get();
    }
    
    public void setPurchase(boolean value) {
        purchase.set(value);
    }
    
    public BooleanProperty purchaseProperty() {
        return purchase;
    }
    

    并添加适当的字符串格式化程序:

    @Override
    public String toString() {
        if(isPurchase()){
            return forPurchaseImmediateCountAndPrice.get("count") + " ($" + forPurchaseImmediateCountAndPrice.get("price") + ")";
        }
        return "0";
    }
    

    在控制器中:

    forPurchaseCol.setCellValueFactory(new PropertyValueFactory<>( "purchase"));
    forPurchaseCol.setCellFactory(new Callback<TableColumn<Product, Boolean>, TableCell<Product, Boolean>>() {
    
        @Override
        public TableCell<Product, Boolean> call(TableColumn<Product, Boolean> col) {
            return new PriceCell();
        }
    });
    

    最后,修改PriceCell

    public class PriceCell extends TableCell<Product, Boolean> {
        private final CheckBox box = new CheckBox();
    
        public PriceCell(){
            box.setOnAction(new EventHandler<ActionEvent>() {
    
                @Override
                public void handle(ActionEvent e) {
                    getTableView().getItems().get(getIndex()).setPurchase(box.isSelected());
                }
            });
        }
    
        @Override
        protected void updateItem(Boolean item, boolean empty) {
            super.updateItem(item, empty);
    
            if(!empty){
                box.setSelected(item);
                setText(getTableView().getItems().get(getIndex()).toString());
                setGraphic(box);
            }
            else {
                setText(null);
                setGraphic(null);
            }
        }
    }
    

    有了这个,你应该不会再遇到滚动问题了。

    【讨论】:

      【解决方案2】:

      您可以在更新 chekBox 单元格值后清除 tableView 并重新重置项目: table.getItems().clear(); table.setItems(getTbleInfo());

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-12-30
        • 2015-12-10
        • 2010-11-04
        • 1970-01-01
        • 1970-01-01
        • 2017-05-04
        • 2010-12-22
        • 1970-01-01
        相关资源
        最近更新 更多