Javafx2.2:滚动表时,表视图中的复选框会搞乱(Javafx2.2: Checkboxes in table view mess up when table is scrolled)

编程入门 行业动态 更新时间:2024-10-24 00:20:27
Javafx2.2:滚动表时,表视图中的复选框会搞乱(Javafx2.2: Checkboxes in table view mess up when table is scrolled)

使用表视图附带的垂直滚动条时会发生此问题。 这就是我的表视图:

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); } } }

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

This issue happens when using the vertical scroll bar that comes with the table view. This is what my table view looks like:

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

When you scroll with the mouse wheel, it's fine. When you scroll with the up/down arrows on the scroll bar, it's fine. But when you actually drag the scroll bar with your mouse pointer, then the selections in the checkboxes get messed up. For instance if you see the image linked above, the third checkbox is selected. After scrolling, the 5th checkbox might now be selected or the 2nd one. Or even two other checkoxes might be selected.

I believe this is a refresh/repaint problem with the table view's scroll bar.

The proper way to solve this would be to intercept the vertical scroll event and manually refresh the grid whenever the user scrolls. To do that I need to be able to get a handle on the table's scrollbar. Something like table.getScrollBar().setEventHandler(this). I am unable to do that. The table's scrollbar seems to be hidden. If I am unable to get to the scroll bar, I can't intercept the scroll event, and I can't fix this problem.

Here is what my fxml looks like:

<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>

Here is the pertinent java code from the controller:

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(); } });

This is what PriceCell.java looks like:

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); } } }

Thanks. Any help is appreciated.

最满意答案

不知怎的,你的模型连接不好......

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

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

已经有一个带有复选框的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); } } }

有了这个,你不应该有滚动问题了。

Somehow your model is not well connected...

PriceCell is trying to mix in one single column two different contents: A boolean for the checkbox, which its state is not stored or processed when the cell is rendered, and which has no field inProduct`, and a string, which is not related to the check state. So when the user clicks the check, the label won't be affected.

While the render seems correct, when you scroll with the mouse the checkbok state is lost, and there's no callback to find it properly.

There's already an implementation of a TableCell with a checkbox: CheckBoxTableCell. But it only takes Boolean as a parameter, since it only needs to know the status (selected or not). You could add some StringConverter for the label, but this is only related to the selected state.

To fix this problem, my suggestions are:

First, create a new field in 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; }

And add a proper string formatter:

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

In the controller:

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(); } });

And finally, modify 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); } } }

With this you shouldn't have problems with the scroll any more.

更多推荐

本文发布于:2023-07-06 07:29:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1047335.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:视图   复选框   Checkboxes   mess   scrolled

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!