TextField inside TableView gone after scroll JavaFX

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-12 04:33:59

问题


I have a table view and inside it, there is one column filled with TextField.

There is no problem when I have few data and my table do not have scroll bar, all TextFields appears.

The problem is, when I scroll down my table and then goes up again, some TextFields are missing.

Here is my code for the column filled with 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);
            }
        });

I really appreciate helps from you guys.

Regards,

Chrisma Andhika


回答1:


Chrisma! The problem you face is a famous issue for JavaFX about updating items in tableview. There is already some workaround about it, for example here. The solution was to trigger tableview's internal update mechanism by

tableview.getColumns().get(0).setVisible(false);
tableview.getColumns().get(0).setVisible(true);

But as far as I could understand this solution affected only changes of data, not the style of tableview's nodes.

I also used

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

with my implementation, but it was not enough, because when there were too many rows in a table and scroll bar appeared the updating of rows became an absolute mess.

What I needed is to make highlighted all visible rows satifying some criteria by using css. I achieved that in the following way:

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

The css file should contain the following lines:

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

Of course you may choose different styling of rows.

The Person class should contain

public SimpleStringProperty firstNameProperty() {
    return firstName;
}

As you can see I added the listener to the VisibleProperty of a row, where I control the css behavior of each row. Maybe this idea could help to solve data update in tableview in some cases, not just rows styling.

I should aslo add that I started receiving the NullPointerException in the public void changed method in the code above, although it doesn't affect the result of my programm.

I hope it will help you, Chrisma! And others as well!




回答2:


I just had that problem with checkboxes. They randomly dissapeared when I scrolled my big table rapidly. I solved it just by deleting this line in my cellFactory:

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



回答3:


Well, I also had the same problem, apparently only draw the visible text field, when we use the scroll does not appear, because only drawing the scene but not the textinputcontrol , so my solution is to capture the scroll event and when you use it to resize the textfield and return it to its original size, thus forcing you to repaint the object, now appear with textinputcontrol.forcing repaint the object, now appear with 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);
                     }
                   }
        }
 });


来源:https://stackoverflow.com/questions/13469661/textfield-inside-tableview-gone-after-scroll-javafx

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!