Javafx 文本多词着色

标签 java colors javafx

好的,我有一个 ListView 对象。我将其用作我的服务器的一种控制台窗口。这真的是我能想到的在这样的框中显示彩色文本的唯一方法。到目前为止,这效果很好。现在我想要做的是在一个索引或行上为不同的文本着色。

示例:

listView[0] = "Hello " + "world";

Hello”为绿色,“world”为蓝色。如果这可以使用 javafx Text 或任何其他方式完成,我想知道如何去做。我使用 Javafx Text 作为主要的罪魁祸首,因为您可以用它自定义很多内容。

我希望每个人都能理解我在这里尝试做的事情,如果不明白,请告诉我,我会尝试改写一下。

解决方案

多亏了 jewelsea,我才找到了解决方案。我采用了一些不同的方法,而不是使用细胞工厂。

ListView

ListView<FlowPane> consoleWindow = new ListView<>();
ArrayList<FlowPane> consoleBuffer = FXCollections.observableArrayList();

consoleWindow.setItems(consoleBuffer);

inputBox.setOnKeyPressed(new EventHandler<KeyEvent>() {
        @Override
        public void handle(KeyEvent keyEvent) {
           if (keyEvent.getCode() == KeyCode.ENTER) {
                consoleBuffer.add(parseInput.parseInputToArray(inputBox.getText()));
           }
            consoleWindow.scrollTo(consoleBuffer.size());
        }
});

ConsoleInputParse:

public class ConsoleInputParse {

    private String[] wordList = {};

    public ConsoleInputParse() {}

    public FlowPane parseInputToArray(String input) {
        wordList = input.trim().split("[ ]+");

        return colorize();
    }

    public FlowPane colorize() {

        ArrayList<Text> textChunks = new ArrayList<>();
        FlowPane bundle = new FlowPane();

        //Todo: use regex to check for valid words
        for (String word : wordList) {
            String spaced = word + " ";
            switch (word) {
                case "Hello": case "hello":
                    textChunks.add(customize(spaced, "purple"));
                    break;
                case "World": case "world":
                    textChunks.add(customize(spaced, "blue"));
                    break;
                case "Stack Overflow":
                    textChunks.add(customize(spaced, "orange", "Arial Bold", 15));
                default:
                    textChunks.add(customize(spaced, "black", "Arial",  13));
                    break;
            }
        }

        bundle.getChildren().addAll(textChunks);
        return bundle;
    }

    public Text customize(String word, String color) {
        return TextBuilder.create().text(word).fill(Paint.valueOf(color)).build();
    }

    public Text customize(String word, String color, String font) {
        return TextBuilder.create()
                .text(word)
                .fill(Paint.valueOf(color))
                .font(Font.font(font, 12)).build();
    }

    public Text customize(String word, String color, String font, int fontSize) {
        return TextBuilder.create()
                .text(word)
                .fill(Paint.valueOf(color))
                .font(Font.font(font, fontSize)).build();
    }

}

1 “工作示例”

最佳答案

创建自定义 cellfactory为您的ListView并让它生成包含 FlowPane 的单元格与不同Text实例,每个都有不同的样式。我创建了一个 sample来演示这个方法。

示例输出:

colorized text

Java 8你可以你可以使用 TextFlow为您的文本设置样式,而不是在 FlowPane 中组合不同的 Text 实例。

示例代码

fruits.css

/** 
 * fruits.css - place in same source directory as FruitsDisplay.java and 
 * ensure the build system copies the file over to the output path
 */
.root {
  -fx-font-size: 20px;
  -fx-font-family: "Comic Sans MS";
}

.list-cell {
  -fx-background-color: azure;
}

.fruit {
  -fx-font-weight: bold;
  -fx-font-style: italic;
}

.apple {
  -fx-fill: forestgreen;
}

.orange {
  -fx-fill: orange;
}

.pear {
  -fx-fill: gold;
}

FruitsDisplay.java

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import javafx.scene.text.Text;
import javafx.stage.Stage;

import java.util.*;

/**
 * Sample of using a FlowPane to create styled text in JavaFX
 */
public class FruitsDisplay extends Application {
    private static final String[] fruits = {"apple", "orange", "pear"};
    private static final String[] fruitImageLocs = {
            "http://weknowyourdreamz.com/images/apple/apple-02.jpg",
            "http://pic.1fotonin.com/data/wallpapers/165/WDF_2048871.png",
            "http://vignette1.wikia.nocookie.net/pikmin/images/c/cc/Pear-01.jpg"
    };
    private Map<String, Image> fruitImages = new HashMap<>();

    public static void main(String[] args) {
        Application.launch(FruitsDisplay.class);
    }

    @Override
    public void start(Stage stage) throws Exception {
        stage.setTitle("Fruit Tales");

        for (int i = 0; i < fruits.length; i++) {
            Image image = new Image(fruitImageLocs[i], 0, 30, true, true);
            fruitImages.put(fruits[i], image);
        }

        ListView<String> list = new ListView<>(FXCollections.observableArrayList(fruits));
        list.setCellFactory(listView -> new FruitFlowCell());
        list.setPrefSize(440, 180);

        Scene scene = new Scene(list);
        scene.getStylesheets().add(getResource("fruits.css"));
        stage.setScene(scene);
        stage.show();
    }

    private String getResource(String resourceName) {
        return getClass().getResource(resourceName).toExternalForm();
    }

    private class FruitFlowCell extends ListCell<String> {
        static final String FRUIT_PLACEHOLDER = "%f";

        {
            setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
        }

        @Override
        protected void updateItem(String s, boolean empty) {
            super.updateItem(s, empty);
            if (s != null && !"".equals(s) && !isEmpty()) {
                setGraphic(createFruitFlow(s));
            } else {
                setGraphic(null);
            }
        }

        private Node createFruitFlow(String s) {
            switch (s) {
                case "apple":
                    return createTextFlow("Eat an ", FRUIT_PLACEHOLDER, s, " a day.");
                case "orange":
                    return createTextFlow("An ", FRUIT_PLACEHOLDER, s, " has many vitamins.");
                case "pear":
                    return createTextFlow("A ", FRUIT_PLACEHOLDER, s, " has a funny shape.");
                default:
                    return null;
            }
        }

        private Node createTextFlow(String... msg) {
            FlowPane flow = new FlowPane();
            boolean isFruit = false;

            for (String s : msg) {
                if (FRUIT_PLACEHOLDER.equals(s)) {
                    isFruit = true;
                    continue;
                }

                Text text = new Text(s);
                if (isFruit) {
                    flow.getChildren().addAll(
                            new ImageView(fruitImages.get(s)),
                            createSpacer(5)
                    );
                    text.getStyleClass().addAll(
                            "fruit",
                            s
                    );
                    isFruit = false;
                } else {
                    text.getStyleClass().add("plain");
                }

                flow.getChildren().add(text);
            }

            return flow;
        }

        private Node createSpacer(int width) {
            HBox spacer = new HBox();
            spacer.setMinWidth(HBox.USE_PREF_SIZE);
            spacer.setPrefWidth(width);
            spacer.setMaxWidth(HBox.USE_PREF_SIZE);

            return spacer;
        }
    }
}

关于Javafx 文本多词着色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15081892/

相关文章:

java - 输出数组中顺序错误的对数?

java - 我如何使用 ObjectContentManager 在节点下添加节点?

java - 从 FXML 初始化加载另一个 FXML

java:比较时间/日期并获得时差的正确格式

java - 什么是NullPointerException,我该如何解决?

java - 改变Java中文本的颜色

html - 将鼠标悬停在链接上时,如何让背景色覆盖它所在的整个框架?

android - 如何更改小部件背景颜色而不丢失其布局角?

css - JavaFX - 无法从元素内加载图像

JavaFX 进度条不更新