mmm
mmm

Reputation: 1446

Get the row from the TableView and UpdateItem override method

I am getting the row from tableView. I use setRowFactory to get row and later I am using it.

I need to override updateItem method to get each row and if item inside that row has error, then use red colour otherwise use green.

The item inside of the row is "history" object, because rows are pieces of history - history, which was created after doing some action in the application.

So I have something like this:

@Override
        protected void updateItem(History history, boolean empty) {
            super.updateItem(history, empty);
            if (empty) {
                setStyle("");
            } else if (history.isHasError() == true) {
                getStyleClass().clear();
                getStyleClass().add("errorHistoryRow");
            } else if (history.isHasError() == false){
                getStyleClass().clear();
                getStyleClass().add("");
            }
        }

But I need to add this updateItem to already defined row in this method.

private void openErrorMessageAfterHoveringOverRow() {

        historyTableView.setRowFactory(tableView -> {
        final TableRow<History> row = new TableRow<>();


        for (History history : model.getAllHistoryObservableArrayList()) {
            ***I NEED TO PUT IT HERE***
        }                   

        for (History his : model.getAllHistoryObservableArrayList()) {

            row.hoverProperty().addListener((observable) -> {
                History historyRow = row.getItem();

                Point p = MouseInfo.getPointerInfo().getLocation();
                int x = p.x;
                int y = p.y;

                Popup popup = new Popup();
                popup.setX(x - 300);
                popup.setY(y - 200);
                TextArea ta = new TextArea();

                AnchorPane layout = new AnchorPane();
                Scene scene = new Scene(layout);
                stageSingleton().setScene(scene);

                if (row.isHover() && his.equals(historyRow)) {
                    ta.setText(row.getItem().getErrorMessage());
                    popup.getContent().addAll(ta);
                    stageSingleton().show();
                    popup.show(stageSingleton());

                } else if (!row.isHover() && his.equals(historyRow)) {
                    popup.hide();
                    stageSingleton().close();
                }
            });
        }
        return row;
    });       
}

So how can I, please, implement method updateItem to already defined row in this method? Because methods below works but I cannot have 2 different "setRowFactory" methods in my project. So I need to merge them in one method.

public void test() {
        historyTableView.setRowFactory(tableView -> new TableRow<History>() {
        @Override
        protected void updateItem(History history, boolean empty) {
            super.updateItem(history, empty);
            if (empty) {
                setStyle("");
            } else if (history.isHasError() == true) {
                getStyleClass().clear();
                getStyleClass().add("errorHistoryRow");
            } else if (history.isHasError() == false){
                getStyleClass().clear();
                getStyleClass().add("");
            }
        }
    });
}

Upvotes: 0

Views: 402

Answers (1)

fabian
fabian

Reputation: 82491

It's impossible to use different rowFactorys (at least you cannot remove the rows that were already created). You need to combine the functionality in the rows returned by your rowFactory.

Some additional notes:

  • You also need to remove the style class, if your row becomes empty. However clearing the style classes interferes with the default style (you remove the table-row-cell style class). It's easier to use a pseudoclass in this case. Moreover adding the empty string as style class is not beneficial in any way.
  • Don't use a InvalidationListener for the hover property. This kind of listener is triggered every time the value changes, if it changes from true to false or the other way round.
public class HistoryRow extends TableRow<History> {

    private static final PseudoClass ERROR = PseudoClass.getPseudoClass("error");

    public HistoryRow() {
        hoverProperty().addListener((o, oldValue, newValue) -> {
            if (newValue) {
                History historyRow = getItem();
                if (historyRow != null && historyRow.isHasError()) {
                    // TODO: display popup here
                } 
            }
        });
    }

    @Override
    protected void updateItem(History history, boolean empty) {
        super.updateItem(history, empty);
        pseudoClassStateChanged(ERROR, !empty && history != null && history.isHasError());
    }

}

In your CSS stylesheet changing from style class to pseudoclass requires you to adjust the selectors. You need to use the :error pseudoclass selector instead of the .errorHistoryRow class selector.

Dynamically changing from erroneous history element to non-erroneous and the other way round could be done by adding a BooleanProperty to History and adding/removing a listener in the updateItem method, if necessary.

Upvotes: 1

Related Questions