This discussion is archived
4 Replies Latest reply: Nov 20, 2011 9:18 PM by JonathanGiles RSS

Setting the color (or other properties) of a single table row

KnutArneVedaa Newbie
Currently Being Moderated
Say I have a data model backing a table view, with a field like e.g. "isDisabled". And for every item where this field is true, I want to set the text color of the table row where the item is displayed to grey, or something otherwise suitable.

It doens't seem that it is possible to use the row factory for this. Do I have to set a cell factory for each cell and set the text color of the cell individually?
  • 1. Re: Setting the color (or other properties) of a single table row
    jsmith Guru
    Currently Being Moderated
    Hi Knut, you could try using css styles for this.
  • 2. Re: Setting the color (or other properties) of a single table row
    KnutArneVedaa Newbie
    Currently Being Moderated
    I don't see how that would work, perhaps I was too unclear. I meant that I had a class such as:
    class Person {
      String name;
      Integer age;
      Boolean isActive;  // let's call it that instead... :)
    }
    and a TableView<Person>.

    Now in this case, for all persons where isActive is false, I want to set the text color on the corresponding row to grey. Now, I could do that either via setTextFill or setStyle or setStyleClass on either the entire row or on each individual cell in the row. But I can't find out how to set properties on a given row.

    Hey! Wait a minute -

    Perhaps the cell has a reference to the row it's part of...ah, yes it has! Let's try it this way:

    (suppose I have the approriate cell value factory)
            isActiveColumn.setCellFactory(new Callback<TableColumn<Person, Boolean>, TableCell<Person, Boolean>>() {
                public TableCell<Person, Boolean> call(TableColumn<Person, Boolean> p) {
                    return new TableCell<Person, Boolean>() {
                        @Override
                        public void updateItem(Boolean item, boolean empty) {
                            super.updateItem(item, empty);                      
                            if (!empty) {
                                if (item != null && !item) {
                                    TableRow row = getTableRow();
                                    System.out.println("row: " + row);
                                    if (row != null) row.setTextFill(Color.GREY);
                                }                            
                            }
                        }                
                    };
                }
            });
    No. That doesn't work. getTableRow() always returns null.

    So...what is the deal with getTableRow(), and how can I achieve the desired result?
  • 3. Re: Setting the color (or other properties) of a single table row
    JonathanGiles Journeyer
    Currently Being Moderated
    I'll take a look into this today as it is something I would like to cover in DataFX (http://www.javafxdata.org). If I have any luck I'll let you know.

    -- Jonathan
  • 4. Re: Setting the color (or other properties) of a single table row
    JonathanGiles Journeyer
    Currently Being Moderated
    I spent a few minutes today extending DataFX (http://www.javafxdata.org) to support styling entire TableView rows via CSS. It's now going to take me considerably longer to describe the API I just provided in DataFX :-)

    So, to start with, this is just a proof of concept. I look forward to you using it and giving me feedback. What you are going to need to do is create a custom TableView row factory, like so:
    tableView.setRowFactory(new Callback<TableView<Person>, TableRow<Person>>() {
        @Override public TableRow<Person> call(TableView<Person> p) {
            final CSSTableRow rowCell = new CSSTableRow() {
                @Override public void getCssState(List s) {
                    super.getCssState(s);
                    s.add(getIndex() % 2 == 0 ? "even" : "odd");
                }
            };
    
            rowCell.getStyleClass().add("alternate-style-test");
    
            return rowCell;
        }
    });
    Basically what I'm doing here is creating a new TableRow on-demand, of type CSSTableRow, which is a class provided in DataFX. I override the getCssState method and add strings to the list that represent the state of that row. In this example, I'm basically using the index value of the row to alternate between "even" and "odd" states. In your case, you'll probably do something like
    tableView.setRowFactory(new Callback<TableView<Person>, TableRow<Person>>() {
        @Override public TableRow<Person> call(TableView<Person> p) {
            final CSSTableRow rowCell = new CSSTableRow() {
                @Override public void getCssState(List s) {
                    super.getCssState(s);
                    if (getItem() != null && getItem().isActive()) s.add("active");
                }
            };
    
            rowCell.getStyleClass().add("active-table-row");
    
            return rowCell;
        }
    });
    The other thing to note is that every row is given a style class. This is how you target them from CSS. So, moving on to CSS, here is the test CSS I wrote for my alternating row colour test:
    .alternate-style-test:even {
        -fx-text-fill: green;
    }
    
    .alternate-style-test:odd {
        -fx-text-fill: red;
    }
    Without doubt you can quite easily connect the dots (and easily appreciate that I am not a designer) :-) All you need to do now is bring in your custom CSS, and hopefully you should get the result you expect.

    If you have any problems, my contact details are on the DataFX website here: http://www.javafxdata.org

    I'll be uploading this new API shortly, in what will be version 0.0.4.

    -- Jonathan

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points