如何在JavaFX形状内插入HTML文本?

3
我想在JavaFx中创建一个基于树的算法可视化,其中有许多下标和上标符号。 我想将这些符号添加到像圆形这样的形状中。
我尝试使用WebView对象实现这一目的,但它会覆盖整个屏幕。
public void start(Stage primaryStage) throws Exception{

        primaryStage.setTitle("Shape Text");
        Group circles = new Group();
        Circle circle = new Circle(50, Color.web("white", 0.7));
        circle.setCenterX(500.0f);
        circle.setCenterY(200.0f);
        circle.setStrokeType(StrokeType.OUTSIDE);
        circle.setStroke(Color.web("white", 0.16));
        circle.setStrokeWidth(4);
        circles.getChildren().add(circle);

        WebView webView = new WebView();
        WebEngine webEngine = webView.getEngine();
        webEngine.loadContent("<h1>B<sub>0</sub></h1>");

        StackPane stack = new StackPane();
        stack.getChildren().addAll(circles, webView);

        Scene scene = new Scene(stack, 1000, 800, Color.BLACK);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

上面的代码用HTML文本替换了整个视图。我也尝试了javafx.scene.text.Text类,但它不支持HTML内容。
提前感谢您!

如果您的所有上标和下标都是数字,则不需要使用WebView。 您可以使用纯文本,因为Unicode包括用于上标和下标数字的字符。例如,new Label("B\u2080") - VGR
2个回答

2

您可能想做以下三件事:

  1. 将WebView的大小调整为HTML内容(或形状的内部显示区域)。
  2. 使WebView页的背景透明
  3. 在WebView中心对齐HTML内容,并将WebView居中放置在Shape中。

sized webview

下面的代码演示了其中一些技巧:

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.StrokeType;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;

import java.lang.reflect.Field;

public class ShapedHTML extends Application {
    @Override
    public void start(Stage stage) throws Exception{
        stage.setTitle("Shape Text");
        Group circles = new Group();
        Circle circle = new Circle(50, Color.web("white", 0.7));
        circle.setCenterX(500.0f);
        circle.setCenterY(200.0f);
        circle.setStrokeType(StrokeType.OUTSIDE);
        circle.setStroke(Color.web("white", 0.16));
        circle.setStrokeWidth(4);
        circles.getChildren().add(circle);

        WebView webView = new WebView();
        WebEngine webEngine = webView.getEngine();
        webView.maxWidthProperty().bind(circle.radiusProperty().multiply(2));
        webView.maxHeightProperty().bind(circle.radiusProperty().multiply(2));
        webEngine.documentProperty().addListener(observable -> {                   
            try {
                // Use reflection to retrieve the WebEngine's private 'page' field.
                Field f = webEngine.getClass().getDeclaredField("page");
                f.setAccessible(true);
                com.sun.webkit.WebPage page = (com.sun.webkit.WebPage) f.get(webEngine);
                page.setBackgroundColor((new java.awt.Color(0, 0, 0, 0)).getRGB());
            } catch (Exception e) {
                System.out.println("Difficulty to make WebView background transparent");
                e.printStackTrace();
            }
        });

        webEngine.loadContent("<h1 id='root' style='background : rgba(0,0,0,0); margin: 0; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);'>B<sub>0</sub></h1>");

        StackPane stack = new StackPane();
        stack.getChildren().addAll(circles, webView);

        Scene scene = new Scene(stack, 1000, 800, Color.BLACK);
        stage.setScene(scene);
        stage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }

}

关于使用com.sun类的注意事项

上述代码使用了com.sun类(通常不建议使用,因为它不是公共支持的API)。但是,在Java 8上它可以工作,并且我不知道更好的方法来实现WebView背景的透明度。

如果您正在使用更高版本的Java(例如Java 11+),则需要提供一些VM参数以允许相关的com.sun类的使用。例如,解决Java 11+中com.sun.webkit.WebPage的可访问性问题,请参见stackoverflow问题Cannot access JavaFX class "WebPage" in IntelliJ-IDEA。该问题的一个答案建议使用以下VM参数(我没有尝试过):

--add-exports javafx.web/com.sun.webkit=projectname

最后一个参数是您项目的 module-info.java 中声明的模块名称。


1
尝试设置 WebViewmaxSize
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;

public class JavaFXTestingGround extends Application
{

    @Override
    public void start(Stage primaryStage) throws Exception
    {
        Circle circle = new Circle(100, Color.web("white", 0.7));

        WebView webView = new WebView();
        WebEngine webEngine = webView.getEngine();
        webEngine.loadContent("<h1>B<sub>0</sub></h1>");
        webView.setMaxSize(50, 50);

        StackPane stack = new StackPane();
        stack.getChildren().addAll(circle, webView);

        Scene scene = new Scene(stack, 1000, 800, Color.BLACK);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接