Java FX:部分更改 ListView 中的颜色?

Java FX: Partly change the color in a ListView?

我有一个包含文件夹路径的 ListView,它显示了添加到程序中的文件夹。

我现在想在每个条目中添加一个单词,具体取决于文件夹是否加密,例如我想添加绿色单词'encrypted'。

我尝试添加带有 html 颜色标签的字符串,但这不起作用。

if (loadedFolders != null) {
    ObservableList<String> list = controller.folderList.getItems();
    for (int i = 0; i < list.size(); i++) {
        
        StringBuilder read = new StringBuilder();
        read.append(list.get(i)).append("<html><font color='red'>test</font></html>");
        controller.folderList.getItems().set(i, read.toString());
    }
}

重要的是,只有添加的单词应该有不同的颜色,其余的保持不变。

您不能使用 HTML 在 JavaFX 中设置字符串样式。您需要做的是为 ListView.

中显示的实际文本添加样式

为此,您需要实现自己的 ListCellListCell 是为您的 ListView 中的每个项目显示的实际单元格。起初看起来令人望而生畏,但它相当简单,并且是您可以有选择地更改数据在 ListView.

中显示方式的唯一方法

下面是一个完整的示例应用程序,您可以通读并运行了解它是如何工作的。

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class ListCellSample extends Application {

    public static void main(String[] args) {

        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {

        // **********************************************************************************************
        // Create a simple base layout
        // **********************************************************************************************
        VBox root = new VBox(5);
        root.setAlignment(Pos.CENTER);
        root.setPadding(new Insets(5));

        // Standard ListView for our sample data
        ListView<Sample> listView = new ListView<>();

        // Create some sample data for the ListView (some encrypted and others not)
        listView.getItems().addAll(
                new Sample("One", false),
                new Sample("Two", true),
                new Sample("Three", false),
                new Sample("Four", true)
                                  );

        // Add the ListView to the layout
        root.getChildren().add(listView);

        // **********************************************************************************************
        // Here we provide our own ListCell using the setCellFactory() method of the ListView
        // **********************************************************************************************
        listView.setCellFactory(lv -> new ListCell<Sample>() {

            // Here we create the reusable layout for each cell. We will use an HBox for the root and labels
            // for the name of the Sample and it's encryption status
            final HBox root = new HBox(5);
            final Label sampleNameLabel = new Label();
            final Label encryptedLabel = new Label("Encrypted");

            // Set the style for the encryptedLabel in a static block
            {
                encryptedLabel.setStyle("-fx-text-fill: green; " +
                                        "-fx-font-style: italic;");

                // Add the sampleNameLabel to the root HBox. We will add the Encrypted label later, if needed
                root.getChildren().add(sampleNameLabel);
            }

            @Override
            protected void updateItem(Sample sample, boolean empty) {

                super.updateItem(sample, empty);

                if (sample == null || empty) {
                    setGraphic(null);

                    // Remove the encrypted label
                    root.getChildren().remove(encryptedLabel);
                } else {

                    // Set the sampleNameLabel to our sample's name
                    sampleNameLabel.setText(sample.getName());

                    // If the Sample is encrypted, add the encryptedLabel to our layout
                    if (sample.isEncrypted()) {
                        root.getChildren().add(encryptedLabel);
                    }

                    // Set our custom layout as the cell's graphic
                    setGraphic(root);
                }
            }
        });

        // Show the application
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }
}

class Sample {

    private final String name;
    private final boolean encrypted;

    public Sample(String name, boolean encrypted) {

        this.name = name;
        this.encrypted = encrypted;
    }

    public String getName() {

        return name;
    }

    public boolean isEncrypted() {

        return encrypted;
    }
}

这就是您最终得到的结果: