滚动JavaFX后,TableView中的TextField消失了

时间:2012-11-20 09:01:41

标签: scrollbar tableview javafx textfield

我有一个表视图,在其中,有一列填充了TextField。

当我的数据很少而且我的表没有滚动条时,没有问题,所有的TextField都出现了。

问题是,当我向下滚动表格然后再次上升时,会丢失一些TextField。

以下是填充TextField的列的代码:

purchaseQtyCol.setCellFactory(
                new Callback<TableColumn< TransactionModel, TextField>, TableCell< TransactionModel, TextField>>() {
                    @Override
                    public TableCell< TransactionModel, TextField> call(final TableColumn< TransactionModel, TextField> p) {
                        TableCell<TransactionModel, TextField> cell = new TableCell<TransactionModel, TextField>() {


                            @Override
                            public void updateItem(TextField item, boolean empty) {
                                super.updateItem(item, empty);
                                if (item != null) {
                                    /**
                                     * for(CheckBox cbb : canceledCB) {
                                     * if(item.equals(cbb))
                                     * System.out.println("aa" +
                                     * this.indexProperty().getValue() + " " +
                                     * item.isSelected() ); }*
                                     */
                                    this.setGraphic(item);
                                }

                            }

                        };

                        cell.setAlignment(Pos.CENTER);
                        return cell;
                    }
                });

        purchaseQtyCol.setCellValueFactory(new Callback<CellDataFeatures<TransactionModel, TextField>, ObservableValue<TextField>>() {
            @Override
            public ObservableValue<TextField> call(final CellDataFeatures<TransactionModel, TextField> p) {

                    System.out.println("new textfield");
                    final TextField qtyField = new TextField() {
                        @Override
                        public void replaceText(int start, int end, String text) {

                            if (text.matches("[0-9]") || text.equals("")) {
                                super.replaceText(start, end, text);
                                if (this.getText().isEmpty()) {
                                    p.getValue().setPurchaseQty(0);
                                    p.getValue().setTotalPrice(0);
                                } else {
                                    p.getValue().setPurchaseQty(Integer.parseInt(this.getText()));
                                    p.getValue().setTotalPrice(p.getValue().purchaseQtyProperty().intValue() * p.getValue().basePriceProperty().intValue());
                                }
                                recountTotals();
                            }
                        }

                        @Override
                        public void replaceSelection(String text) {

                            if (text.matches("[0-9]") || text.equals("")) {
                                super.replaceSelection(text);
                                if (this.getText().isEmpty()) {
                                    p.getValue().setPurchaseQty(0);
                                    p.getValue().setTotalPrice(0);
                                } else {
                                    p.getValue().setPurchaseQty(Integer.parseInt(this.getText()));
                                    p.getValue().setTotalPrice(p.getValue().purchaseQtyProperty().intValue() * p.getValue().basePriceProperty().intValue());
                                }
                                recountTotals();
                            }
                        }
                    };

                    qtyField.setText("" + p.getValue().purchaseQtyProperty().getValue());
                    qtyField.setAlignment(Pos.CENTER_RIGHT);

                return new SimpleObjectProperty(qtyField);
            }
        });

我非常感谢你们的帮助。

此致

Chrisma Andhika

3 个答案:

答案 0 :(得分:1)

Chrisma!您遇到的问题是JavaFX关于更新tableview中项目的一个着名问题。已经有一些解决方法,例如here。解决方案是通过

触发tableview的内部更新机制
tableview.getColumns().get(0).setVisible(false);
tableview.getColumns().get(0).setVisible(true);

但据我所知,此解决方案仅影响数据的更改,而不影响tableview节点的样式。

我也用过

@Override
public void updateItem(Object item, boolean empty)

我的实现,但这还不够,因为当表中有太多行并且滚动条出现时,行的更新变得非常混乱。

我需要的是使用css突出显示所有可见行,以满足某些标准。我通过以下方式实现了这一目标:

Callback<TableView<Person>, TableRow<Person>> callBack = 
    new Callback<TableView<Person>, TableRow<Person>>() {
        @Override
        public TableRow<Person> call(TableView<Person> tableView) {
              final TableRow<Person> row = new TableRow<Person>() {
                     @Override
                     public void updateItem(Person item, boolean empty) {
                          super.updateItem(item, empty);
                          if(!empty && item.getFirstName() == "John") {
                              getStyleClass().add("john");
                          }
                     }
               };
               row.visibleProperty().addListener(new ChangeListener() {
                     @Override
                     public void changed(ObservableValue observableValue, Object t, Object t1) {
                         Boolean oldValue = (Boolean)t;
                         Boolean newValue = (Boolean)t1;
                         if(oldValue && !newValue) {
                             row.getStyleClass().remove("john");
                         }
                         if(!oldValue && newValue) {
                             if(row.getItem().getFirstName() == "John")
                                 row.getStyleClass().add("john");
                         }
                     }
               });
               return row;
        }
};
tableview.setRowFactory(callBack);

css文件应包含以下行:

.john {
-fx-background-color: forestgreen;
-fx-text-fill: white;
-fx-border-style: solid;
}

当然,您可以选择不同的行样式。

Person类应包含

public SimpleStringProperty firstNameProperty() {
    return firstName;
}

正如您所看到的,我将侦听器添加到行的VisibleProperty,在那里我控制每行的css行为。在某些情况下,这个想法可能有助于解决tableview中的数据更新问题,而不仅仅是行样式。

我还应该补充一点,我开始在上面的代码中的NullPointerException方法中收到public void changed,但它不会影响我的程序结果。

我希望它会对你有所帮助,Chrisma!还有其他人!

答案 1 :(得分:0)

我刚刚遇到了复选框的问题。当我快速滚动我的大桌子时,它们随机消失了。我只是在我的单元格工厂中删除了这一行来解决它:

   @Override
    public void updateItem(Boolean item, boolean empty) {
        super.updateItem(item, empty);
       if (empty) {
           setText(null);
           // setGraphic(null); (This line causes weird behaviour in scrolling, delete it)
        } else {
            checkBox.setSelected(item);
        }
    }

答案 2 :(得分:0)

好吧,我也有同样的问题,显然只画了可见文本字段,当我们使用滚动时没有出现,因为只绘制场景而不是textinputcontrol,所以我的解决方案是捕获滚动事件和何时您使用它来调整文本字段的大小并将其恢复为原始大小,从而强制您重新绘制对象,现在显示为textinputcontrol.forcing重新绘制对象,现在显示为textinputcontrol。

 tableview.addEventFilter(ScrollEvent.ANY, new EventHandler<ScrollEvent>() {
        @Override
        public void handle(ScrollEvent scrollEvent) {
           System.out.println("Scrolled.");
            for(ObservableList<TextField> i:data)
                   {
                     for(TextField j: i)
                     {
                   j.setPrefSize(141, 31);
                   j.setPrefSize(140, 30);
                     }
                   }
        }
 });