【问题标题】:Javafx: TableView change row color based on column valueJavafx:TableView 根据列值更改行颜色
【发布时间】:2015-09-02 13:54:01
【问题描述】:

我有以下代码来更新列单元格及其对应行的颜色:

    calltypel.setCellFactory(column -> {
        return new TableCell<CallLogs, String>() {
            @Override
            protected void updateItem(String item, boolean empty) {
                super.updateItem(item, empty);

                setText(empty ? "" : getItem().toString());
                setGraphic(null);

                TableRow currentRow = getTableRow();

                //This doesn't work
                if(item.equals("a")){
                    item.setTextFill(Color.RED);
                    currentRow.setTextFill(Color.PINK);
                    }
                else{
                    item.setTextFill(Color.GREEN);
                    currentRow.setTextFill(Color.BLUE);
                }

            }
        };
    });

'if' 条件的代码段不起作用。我无法识别对对象的正确引用,以及执行此操作的最佳方法。

谢谢!

【问题讨论】:

  • item 是 String 所以你不能做 item.setTextFill()。而是调用 this.setTextFill()。如果一个单元格是“a”而另一个不是,会发生什么情况,行的颜色是什么?
  • 在这两种情况下,颜色是不同的。但是行着色不起作用。事实上,item.equals 不起作用。
  • 我试过if (!isEmpty()) { this.setTextFill(Color.GREEN); if(item.equals("missed call")) this.setTextFill(Color.RED);} 并且这行得通,但这不是我希望写if 子句的方式。另外,如何设置整行的文字颜色?

标签: javafx javafx-2 javafx-8


【解决方案1】:
private void customiseFactory(TableColumn<CallLogs, String> calltypel) {
    calltypel.setCellFactory(column -> {
        return new TableCell<CallLogs, String>() {
            @Override
            protected void updateItem(String item, boolean empty) {
                super.updateItem(item, empty);

                setText(empty ? "" : getItem().toString());
                setGraphic(null);

                TableRow<CallLogs> currentRow = getTableRow();

                if (!isEmpty()) {

                    if(item.equals("a")) 
                        currentRow.setStyle("-fx-background-color:lightcoral");
                    else
                        currentRow.setStyle("-fx-background-color:lightgreen");
                }
            }
        };
    });
}

这行得通!

【讨论】:

  • 什么是calltypel?
  • 当用户隐藏列(可见性属性)时这将失败
  • 这个答案没有用,因为没有指定变量 calltypel 的类型。
  • @MateusViccari calltypel 应该是一个 TableColumn 对象。
  • 我有 30 行的表,只有 7 行可见。列值是整数,我只想要编号为 3 的颜色行。但是当我上下滚动(显示除这 7 行之外的其他行)时,更多行会被着色。一段时间后,我可以为所有行着色。 @BlueWizard 我需要看看你是什么意思。
【解决方案2】:

我最近对这个主题做了一些研究。使用以下代码,您可以根据列值更改 TableView 的行颜色(我会尽力解释它)。

我们要做的第一件事就是定义这个TableView和这个TableView的Columns:

private TableView<Person> personTable;
private TableColumn<Person, String> nameColumn;
private TableColumn<Person, String> lastNameColumn;

下一步是定义其中一列的 Cell Factory:

nameColumn.setCellFactory(column -> {
    return new TableCell<Person, String>() {
        @Override
        protected void updateItem(String item, boolean empty) {
            super.updateItem(item, empty); //This is mandatory

            if (item == null || empty) { //If the cell is empty
                setText(null);
                setStyle("");
            } else { //If the cell is not empty

                setText(item); //Put the String data in the cell

                //We get here all the info of the Person of this row
                Person auxPerson = getTableView().getItems().get(getIndex());

                // Style all persons wich name is "Edgard"
                if (auxPerson.getName().equals("Edgard")) {
                    setTextFill(Color.RED); //The text in red
                    setStyle("-fx-background-color: yellow"); //The background of the cell in yellow
                } else {
                    //Here I see if the row of this cell is selected or not
                    if(getTableView().getSelectionModel().getSelectedItems().contains(auxPerson))
                        setTextFill(Color.WHITE);
                    else
                        setTextFill(Color.BLACK);
                }
            }
        }
    };
});

代码逻辑:我们覆盖的updateItem()方法,当底层item发生变化时会自动调用。

我们收到必须呈现的数据项(在本例中为字符串)。如果项目为空或 null(例如空单元格),我们不应用任何样式。否则,我们根据人物名称设置项目的格式、设置单元格的文本以及颜色和背景。

如果要在表格的其他列中应用单元格的这种颜色,我们必须使用“行工厂”而不是“单元工厂”,但代码的逻辑类似:

personTable.setRowFactory(row -> new TableRow<Person>(){
    @Override
    public void updateItem(Person item, boolean empty){
        super.updateItem(item, empty);

        if (item == null || empty) {
            setStyle("");
        } else {
            //Now 'item' has all the info of the Person in this row
            if (item.getName().equals("Edgar")) {
                //We apply now the changes in all the cells of the row
                for(int i=0; i<getChildren().size();i++){
                    ((Labeled) getChildren().get(i)).setTextFill(Color.RED);
                    ((Labeled) getChildren().get(i)).setStyle("-fx-background-color: yellow");
                }                        
            } else {
                if(getTableView().getSelectionModel().getSelectedItems().contains(item)){
                    for(int i=0; i<getChildren().size();i++){
                        ((Labeled) getChildren().get(i)).setTextFill(Color.WHITE);;
                    }
                }
                else{
                    for(int i=0; i<getChildren().size();i++){
                        ((Labeled) getChildren().get(i)).setTextFill(Color.BLACK);;
                    }
                }
            }
        }
    }
});

这是我发现在行的所有单元格中应用样式更改的最佳方法。如果在 Cell Factory 中使用“getTableRow()”方法,则无法修改其子单元格。

注意 1:如果要更改文本的样式,则必须在单元格中工作。如果您尝试直接对行进行此更改,则没有任何效果。

注意 2:如果您使用的是单独的 CSS 文件,请不要这样写:

.table-cell {
    -fx-text-fill: Black;
}

因为如果你这样做,所有的 Java 代码都没有效果。

【讨论】:

  • The logic of the code: the updateItem() method that we overwrite, it's called automatically whenever the cell has to be rendered. ... 这不是真的。顾名思义,它仅在底层项目更改时调用,而不是在调整大小时调用。
  • 我正在使用这个解决方案,它部分工作......在我滚动之前,行不会改变它的颜色......有什么建议吗?
【解决方案3】:

正确的做法是使用setRowFactory的表:

table.setRowFactory(tv -> new TableRow<CustomItem>() {
    @Override
    protected void updateItem(CustomItem item, boolean empty) {
        super.updateItem(item, empty);
        if (item == null || item.getValue() == null)
            setStyle("");
        else if (item.getValue() > 0)
            setStyle("-fx-background-color: #baffba;");
        else if (item.getValue() < 0)
            setStyle("-fx-background-color: #ffd7d1;");
        else
            setStyle("");
    }
});

【讨论】:

    【解决方案4】:

    经过多次搜索,我找到了答案。您需要为表中的特定行设置一个 ID,并根据行 ID 在外部 css 文件中设置颜色。这是我将错误行的颜色更改为红色的示例。 Java 代码:

    resultsTable.setRowFactory(row -> new TableRow<Result>() {
                @Override
                public void updateItem(Result item, boolean empty) {
                    super.updateItem(item, empty);
                    if (item == null) {
                        setStyle("");
                    } else if (item.getResultType().equalsIgnoreCase("Error")) {
                        this.setId("error");
                    } else {
                        this.setId("not-error");
                    }
                }
            });
    

    CSS 文件:

    #error .text{
        -fx-fill : red;
    }
    
    #not-error .text{
        -fx-fill : black;
    }

    【讨论】:

    • 虽然可能,但这不是最好的方法:a) id 在场景中应该是唯一的(尽管没有强制执行)b) 如果您使用它并根据内容设置一个或另一个,您必须如果为空或为空,则重置它。其他答案中的样式应该可以正常工作。另一种方法是使用pseudoClasses(这里有几个QA,但是没有任何参考资料,sry)
    猜你喜欢
    • 1970-01-01
    • 2013-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-10
    • 2014-09-10
    相关资源
    最近更新 更多