【问题标题】:Various Colours In The Same Table Cell, Possible?同一个表格单元格中的各种颜色,可能吗?
【发布时间】:2022-10-15 04:33:28
【问题描述】:

我有一个请求在表格单元格中显示各种颜色的字符串,即字符串的一部分以一种颜色显示,其余部分以另一种颜色显示(背景或文本)。我发现an article 更改单元格文本颜色或背景颜色,但不是单元格的一部分。接近要求,但不符合要求。

我能想到的唯一可能的解决方案是使用 Text 类型,在将字符串分成两部分后可以设置各种颜色。但是,如何在 TableView 设置中使用 Text 类型数据,如下所示?

aColumn.setCellValueFactory(p -> new SimpleStringProperty(...) );
...
aTalbeView.setItems(FXcollections.observableArrayList(...));

我还是 JavaFX 的新手。可行吗?如果是这样,我该如何解决?

附上一张模拟表,如下所示:

【问题讨论】:

  • 您需要设置cellFactorycellValueFactory
  • 对于这样的视觉问题,最好提供一个表格的模型图像,以及单元格和文本的颜色,然后你就有更好的机会收到更接近你的答案的答案正在努力实现。
  • @jewelsea 你是 100% 正确的。我不知道我可以在 Stackoverflow 上的问题中附加图像文件。加一个就行了。

标签: javafx


【解决方案1】:

cellValueFactory 用于告诉单元格什么数据显示。告诉细胞如何显示它的数据,使用cellFactory。两者或多或少是独立的。

所以你可以做

aColumn.setCellValueFactory(p -> new SimpleStringProperty(...));

然后是这样的:

aColumn.setCellFactory(tc -> new TableCell<>() {
    private final String[] palette = new String[] {
        "#1B9E77", "#D95F02", "#7570B3", "#E7298A",
        "#66A61E", "#E6AB02", "#A6761D", "#666666" };
    private TextFlow flow = new TextFlow();

    @Override
    protected void updateItem(String item, boolean empty) {
        super.updateItem(item, empty);
        if (empty || item == null) {
            setGraphic(null);
        } else {
            flow.getChildren().clear();
            int i = 0 ;
            for (String word : item.split("\s")) {
                Text text = new Text(word);
                text.setFill(Color.web(palette[i++ % palette.length]);
                flow.getChildren().add(text);
                flow.getChildren().add(new Text(" "));
            }
            setGraphic(flow);
        }
    }
});

这假设每个单元格都有多个单词(由空格分隔)并将每个单词着色为不同的颜色。您可以以任何您喜欢的方式实现不同的颜色;这显示了基本思想。

【讨论】:

  • 非常感谢您的代码示例。明天我将尝试代码。
  • 只是想知道您将哪个版本的 org.openjfx 用于代码。我假设 javafx.scene.text.TextFlow 是您代码中的类。如果是这样,它在发行版 19 中没有这些方法。
  • @vic 是的,对不起。这将教我在不测试的情况下发布代码(尽管我会指出,如果您希望人们发布他们实际运行过的答案,那么如果您提供 minimal reproducible example 供他们使用,则更有可能做到这一点)。当然应该是flow.getChildren()
  • 感谢您的信息。我得到它编译。我知道如何更改表格中的文本颜色。虽然只有绿色应用于文本,但代码中有一个错误。我稍后会尝试修复它。
  • @vic 已修复。见编辑。
【解决方案2】:

示例代码

稍后将编辑答案和代码的一些解释。

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.*;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class HighlightedTextTableViewer extends Application {

    private static final String CSS_DATA_URL = "data:text/css,";
    private static final String HIGHLIGHTABLE_LABEL_CSS = CSS_DATA_URL + // language=CSS
            """
            .highlightable {
                -fx-font-family: monospace; 
                -fx-font-weight: bold;
            }
            
            .highlight {
                 -fx-background-color: cornflowerblue;
                 -fx-text-fill: white;
            }
            """;

    private static final String HIGHLIGHTABLE_STYLE_CLASS = "highlightable";
    private static final String HIGHLIGHTED_STYLE_CLASS = "highlight";

    @Override
    public void start(Stage stage) {
        TableView<Field> table = createTable();
        populateTable(table);

        VBox layout = new VBox(
                10,
                table
        );
        layout.setPadding(new Insets(10));
        layout.setPrefHeight(100);

        stage.setScene(new Scene(layout));
        stage.show();
    }

    private TableView<Field> createTable() {
        TableView<Field> table = new TableView<>();

        TableColumn<Field, String> nameColumn = new TableColumn<>("Name");
        nameColumn.setCellValueFactory(
                p -> p.getValue().nameProperty()
        );

        TableColumn<Field, Field> valueColumn = new TableColumn<>("Value");
        valueColumn.setCellValueFactory(
                p -> Bindings.createObjectBinding(
                        p::getValue,
                        p.getValue().valueProperty(), p.getValue().highlightRangeProperty()
                )
        );
        valueColumn.setCellFactory(param -> new HighlightableTextCell());

        //noinspection unchecked
        table.getColumns().setAll(nameColumn, valueColumn);

        return table;
    }

    public static class HighlightableTextCell extends TableCell<Field, Field> {
        protected void updateItem(Field item, boolean empty) {
            super.updateItem(item, empty);

            if (item == null || empty || item.getValue() == null) {
                setGraphic(null);
            } else {
                setGraphic(constructTextBox(item));
            }
        }

        private Node constructTextBox(Field item) {
            HBox textBox = new HBox();
            textBox.getStylesheets().setAll(HIGHLIGHTABLE_LABEL_CSS);
            textBox.getStyleClass().add(HIGHLIGHTABLE_STYLE_CLASS);

            int from = item.getHighlightRange() != null ? item.getHighlightRange().from() : -1;
            int valueLen = item.getValue() != null ? item.getValue().length() : -1;
            int to = item.getHighlightRange() != null ? item.getHighlightRange().to() : -1;

            if (item.highlightRangeProperty() == null
                    || from >= to
                    || from > valueLen
            ) { // no highlight specified or no highlight in range.
                textBox.getChildren().add(
                        createStyledLabel(
                                item.getValue()
                        )
                );
            } else {
                textBox.getChildren().add(
                        createStyledLabel(
                                item.getValue().substring(
                                        0,
                                        from
                                )
                        )
                );

                if (from >= valueLen) {
                    return textBox;
                }

                textBox.getChildren().add(
                        createStyledLabel(
                                item.getValue().substring(
                                        from,
                                        Math.min(valueLen, to)
                                ), HIGHLIGHTED_STYLE_CLASS
                        )
                );

                if (to >= valueLen) {
                    return textBox;
                }

                textBox.getChildren().add(
                        createStyledLabel(
                                item.getValue().substring(
                                        to
                                )
                        )
                );
            }

            return textBox;
        }

        private Label createStyledLabel(String value, String... styleClasses) {
            Label label = new Label(value);
            label.getStyleClass().setAll(styleClasses);

            return label;
        }
    }

    private void populateTable(TableView<Field> table) {
        table.getItems().addAll(
                new Field("Dragon", "93 6d 6d da", null),
                new Field("Rainbow", "0c fb ff 1c", new Range(3, 8))
        );
    }

}

class Field {
    private final StringProperty name;
    private final StringProperty value;
    private final ObjectProperty<Range> highlightRange;

    public Field(String name, String value, Range highlightRange) {
        this.name = new SimpleStringProperty(name);
        this.value = new SimpleStringProperty(value);
        this.highlightRange = new SimpleObjectProperty<>(highlightRange);
    }

    public String getName() {
        return name.get();
    }

    public StringProperty nameProperty() {
        return name;
    }

    public void setName(String name) {
        this.name.set(name);
    }

    public String getValue() {
        return value.get();
    }

    public StringProperty valueProperty() {
        return value;
    }

    public void setValue(String value) {
        this.value.set(value);
    }

    public Range getHighlightRange() {
        return highlightRange.get();
    }

    public ObjectProperty<Range> highlightRangeProperty() {
        return highlightRange;
    }

    public void setHighlightRange(Range highlightRange) {
        this.highlightRange.set(highlightRange);
    }
}

record Range(int from, int to) {}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-15
    • 2014-12-30
    • 1970-01-01
    • 1970-01-01
    • 2015-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多