简体   繁体   中英

Change TableRow color based on content

I want to make a table that changes row color based on row's content. Therefore I use the following code. I did this by myself and that seems to be the cause of the problem ;) because the part where the row background is set seems not to work as intended:

Not the row with the GOODFRIENDS changes it's color but the one above. As you see I placed a System.out.println(row.getItem()); before the color is set to be sure that the row is the right 'row'. - And it is. So at that point I have no idea why always the wrong row is colored while the row reference at runtime is another (the right one).

Any ideas?

personTable.setRowFactory(new Callback<TableView<Person>, TableRow<Person>>() {

        Person person;
        int counter = 0;

        @Override
        public TableRow<Person> call(TableView<Person> tableView) {
            TableRow<Person> row = new TableRow<>();

            if (counter < tableView.getItems().size() && (person = tableView.getItems().get(counter)) != null) {
                row.setItem(person);
                counter++;
            }

            if (row.getItem() != null && row.getItem().getState() == State.GOODFRIEND) {
                System.out.println(row.getItem());
                row.setStyle("-fx-background-color: green;");
                //OR
                row.setBackground(new Background(
                        new BackgroundFill(Color.LIGHTGREEN, CornerRadii.EMPTY, new Insets(3, 0, 3, 0))));
            }

            row.setOnMouseClicked....

        return row;
    }

UPDATE: James_D solution works fine for coloring the rows, but the sedOnMouseClicked event doesn't work, because they are based on now empty row objects.

    row.setOnMouseClicked(mouseEvent -> {
            if (!row.isEmpty()) {
                defriend_Button.setDisable(false);
                if (row.getItem().getState() == State.FRIEND) {
                    goodFriend_Button.setDisable(false);
                } else {
                    goodFriend_Button.setDisable(true);
                }
            } else if (row.isEmpty()) {
                personTable.getSelectionModel().select(null);
                defriend_Button.setDisable(true);
                goodfriend_Button.setDisable(true);
            }

            if (mouseEvent.getClickCount() == 2 && (!row.isEmpty())) {
                controller.showFriendDescriptionView(row.getItem());
            }
        });

You seem to be assuming that a single table row will be created for each item in the table, and in the order that the items exist. There is no such guarantee, and in fact in most cases this won't happen. TableRow s are essentially created for each visible row (whether or not they contain an item), and are reused to display different items as the user scrolls or the items displayed change for other reasons.

So you need to override the updateItem(...) method and perform the logic there.

personTable.setRowFactory(tv -> {
    TableRow<Person> row = new TableRow<Person>() {
        @Override
        public void updateItem(Person person, boolean empty) {
            super.updateItem(person, empty);
            if (person != null && person.getState() == State.GOODFRIEND) {
                setStyle("-fx-background-color: green;");
            } else {
                setStyle("");
            }
        }
    };
    row.setOnMouseClicked(...);
    return row ;
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM