有没有办法在 JavaFX 的同一文本行中使用两种不同的字体大小?

Is there a way to have two different font sizes within the same text line in JavaFX?

我正在使用 Java 制作一个 windows-运行- 移动概念股票市场游戏,它是 JavaFX 库,我想要在玩家当前余额的右下方显示货币形式(在我的例子中是美元)。这样做的问题是,每当玩家在游戏中获得 1000 美元的倍数时,玩家的余额就会变大,这意味着持有玩家余额的绳子也会变大。这导致字符串"USD"在应用程序中的固定位置与玩家当前余额重叠。

我试过只要数字增加一千的倍数,就强制程序移动 "USD" 符号。然而,这似乎非常低效,我敢打赌,有一种更简单的方法可以做到这一点。

    double balance = 12313.00;

    DecimalFormat decimalFormat = new DecimalFormat("#,###");
    String numberAsString = decimalFormat.format(balance);

    Text balanceText = new Text("$" + (numberAsString));
    balanceText.setFont(Font.font("Modernist", 72));
    balanceText.setFill(Color.web("77e6b3"));
    balanceText.setLayoutX(25);
    balanceText.setLayoutY(250);

    Text currencyText = new Text("USD");
    currencyText.setFont(Font.font("Modernist", 36));
    currencyText.setFill(Color.web("77e6b3"));
    currencyText.setLayoutX(275);
    currencyText.setLayoutY(250);

与其尝试手动设置 Text 节点的 X/Y 坐标,不如利用许多内置的 JavaFX Layout Panes.

通过在 JavaFX 中混合不同的布局面板,您可以轻松构建非常复杂的 UI 布局。每个 Pane 都可以彼此独立地设置样式和配置,每个都应用不同的布局 "rules"。

我建议通读上面的 link 以更好地了解可用的内容,但对于你的问题,我在下面提供了一个完整的示例。


基本上,我们使用 HBox 来保持玩家的余额和水平方向的货币名称。由于我们的玩家货币有一个完全独立的 Label,当我们增加 Label 的值或字体大小时,界面的其余部分不会受到影响(这意味着货币类型可以保持相同的大小).

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

public class GrowingTextSample extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {

        // Simple Interface
        VBox root = new VBox(10);
        root.setAlignment(Pos.CENTER);
        root.setPadding(new Insets(10));

        // Here we'll create a simple HBox to hold our player balance and currency type. By using a HBox, we can add
        // multiple Label (or Text) objects and style/size them separately
        HBox hbPlayerBalance = new HBox(5);
        hbPlayerBalance.setAlignment(Pos.CENTER);

        // Let's create a Label to hold the player's current balance. For this example, I'm going to use a text Label
        // to hold our Integer value. In a real application, you would want to use a special Binding to keep the TextProperty
        // of the Label in sync with an Integer or Double value.
        Label lblPlayerBalance = new Label("0");

        // Here is our label for the currency type
        Label lblCurrency = new Label("USD");

        // Add our labels to the HBox
        hbPlayerBalance.getChildren().addAll(lblPlayerBalance, lblCurrency);

        // Create a Button that simulates an increase to the player's balance. Again, this is just a crude demonstration
        // of how the layout panes (HBox, in this case) work to keep your layout clean and responsive.
        Button btnIncreaseBalance = new Button("Get Rich");

        // Add an action to our Button
        btnIncreaseBalance.setOnAction(event -> {

            // Change balance value
            lblPlayerBalance.setText("12,322,242");

            // Change balance font size. Notice changing the font size of the balance does not affect the currency Label
            lblPlayerBalance.setStyle("-fx-font-size: 200%;");

        });

        // Add the HBox and Button to our root layout
        root.getChildren().addAll(hbPlayerBalance, btnIncreaseBalance);

        // Show the stage
        primaryStage.setScene(new Scene(root));
        primaryStage.setHeight(200);
        primaryStage.setWidth(300);
        primaryStage.setTitle("GrowingTextSample Sample");
        primaryStage.show();

    }
}

结果:


Note: There are a lot of additional formatting and styling options available to make sure your layout is exactly how you'd expect. You'll need to read through the JavaDocs or find additional tutorials to learn more. This answer is only meant to demonstrate one of many possible solutions.

您可以使用 TextFlow 以多种字体、大小、样式和颜色呈现富文本:

示例代码

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.*;
import javafx.scene.text.TextFlow;
import javafx.stage.Stage;

import java.text.DecimalFormat;

public class MoMoney extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        double balance = 12313.00;

        DecimalFormat decimalFormat = new DecimalFormat("#,###");
        String numberAsString = decimalFormat.format(balance);

        Text balanceText = new Text("$" + (numberAsString));
        balanceText.setFont(Font.font("Modernist", 72));
        balanceText.setFill(Color.web("77e6b3"));

        Text currencyText = new Text("USD");
        currencyText.setTextOrigin(VPos.TOP);
        currencyText.setFont(Font.font("Modernist", 36));
        currencyText.setFill(Color.web("77e6b3"));

        TextFlow flow = new TextFlow(balanceText, currencyText);
        flow.setMinSize(TextFlow.USE_PREF_SIZE, TextFlow.USE_PREF_SIZE);

        VBox layout = new VBox(flow);
        layout.setPadding(new Insets(10));

        stage.setScene(new Scene(layout));
        stage.getScene().setFill(Color.rgb(35, 39, 50));
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

JavaDoc 说明

上面链接的 JavaDoc 中的 TextFlow 描述:

TextFlow is special layout designed to lay out rich text. It can be used to layout several Text nodes in a single text flow. The TextFlow uses the text and the font of each Text node inside of it plus it own width and text alignment to determine the location for each child.

实施意见

默认情况下,如果没有足够的 space 来呈现所有文本,TextFlow 会将文本换行,因此我将 TextFlow 的最小大小设置为其首选大小以防止出现这种情况。

TextFlow 可以使用基于标准宽度的对齐设置(例如左对齐、右对齐、两端对齐等)来对齐文本。但是,TextFlow 无法垂直对齐文本,例如生成上标值。还有其他限制,例如使文本可选择用于复制和粘贴或编辑文本。所以看看它,并尝试看看它是否符合您的目的,如果不符合,请考虑下面提到的其他一些替代机制。

替代方法

其他有效的方法是:

  1. 使用带约束的布局容器来控制布局(如 Zephyr 的回答和相关问题:Javafx Text multi-word colorization)。
  2. 嵌入 WebView 以呈现 CSS 格式 html。
  3. 使用第三方库,例如 RichTextFX