You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在javafx.scene.Canvas中直接绘制Ikonli的FontIcon(kordamp 12.3.1)

在JavaFX Canvas中绘制Ikonli FontIcon的问题

我需要在javafx.scene.Canvas中直接绘制Ikonli的FontIcon(使用kordamp 12.3.1版本),目标是让左侧的图标显示在右侧的Canvas上。目前我通过快照方式尝试实现,但显示效果不正确。我认为存在其他实现方式,比如获取SVG,但尚未找到基于Ikonli的可行方案。

效果截图:
Canvas上图标显示异常

当前代码:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
 
import javafx.scene.image.Image;
 
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;

import javafx.stage.Stage;

import org.kordamp.ikonli.fontawesome5.FontAwesomeSolid;
import org.kordamp.ikonli.javafx.FontIcon;
 

public class IkonliCanvas extends Application {
   
    
    @Override
    public void start(Stage primaryStage) {
        // 创建Canvas
        Canvas canvas = new Canvas(100, 400 );
        GraphicsContext gc = canvas.getGraphicsContext2D();        
        
        Pane pcanvas = new Pane();
        pcanvas.getChildren().add(canvas); 
        
        FontIcon fi = new FontIcon(FontAwesomeSolid.APPLE_ALT);      
        fi.setIconSize(30);
    
        Image snapshot = fi.snapshot(new SnapshotParameters(), null);       
        gc.drawImage(snapshot, 40,100);
        
        
        Pane p = new Pane();
        p.getChildren().add(fi);
        p.setPrefWidth(100);        
        fi.setLayoutX(40);
        fi.setLayoutY(100); 
        
        BorderPane bp = new BorderPane();
        bp.setLeft(p);
        bp.setCenter(pcanvas);
             
        Scene scene = new Scene(bp, 220,400);
    
        primaryStage.setScene(scene);
        primaryStage.setTitle("Canvas Ikonli");
        primaryStage.show();
    }
 
    public static void main(String[] args) {
        launch(args);
    }
    
}

解决方案

方法一:修复快照渲染问题

快照失效的核心原因是FontIcon还未完成布局和渲染就被执行快照操作。只需将快照逻辑延迟到JavaFX渲染队列的下一帧,确保图标先完成渲染:

修改代码中的快照部分:

// 原快照代码替换为以下内容
fi.applyCss();
fi.layout();

// 延迟到下一帧执行快照
Platform.runLater(() -> {
    Image snapshot = fi.snapshot(new SnapshotParameters(), null);
    gc.drawImage(snapshot, 40, 100);
});

注意需要导入javafx.application.Platform包。

方法二:直接绘制SVG路径(更高效)

Ikonli的FontIcon本质是矢量图形,可直接获取其SVG路径数据,通过Canvas的GraphicsContext绘制,避免快照的性能开销:

示例代码:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.SVGPath;
import javafx.stage.Stage;
import org.kordamp.ikonli.fontawesome5.FontAwesomeSolid;
import org.kordamp.ikonli.javafx.FontIcon;

public class IkonliCanvas extends Application {

    @Override
    public void start(Stage primaryStage) {
        Canvas canvas = new Canvas(100, 400);
        GraphicsContext gc = canvas.getGraphicsContext2D();
        Pane pcanvas = new Pane(canvas);

        // 获取FontIcon的SVG路径数据
        FontIcon fi = new FontIcon(FontAwesomeSolid.APPLE_ALT);
        fi.setIconSize(30);
        String svgPathData = fi.getIcon().getDescription();

        // 初始化SVGPath并设置路径内容
        SVGPath svgPath = new SVGPath();
        svgPath.setContent(svgPathData);

        // 设置绘制参数
        gc.setFill(Color.BLACK); // 对应FontIcon的iconColor属性
        gc.translate(40, 100); // 图标位置偏移
        // 按图标大小缩放,Ikonli默认基准大小为16px
        gc.scale(fi.getIconSize() / 16.0, fi.getIconSize() / 16.0);

        // 在Canvas上绘制路径
        gc.fill(svgPath);

        // 左侧显示原图标用于对比
        Pane p = new Pane(fi);
        p.setPrefWidth(100);
        fi.setLayoutX(40);
        fi.setLayoutY(100);

        BorderPane bp = new BorderPane();
        bp.setLeft(p);
        bp.setCenter(pcanvas);

        Scene scene = new Scene(bp, 220, 400);
        primaryStage.setScene(scene);
        primaryStage.setTitle("Canvas Ikonli");
        primaryStage.show();
    }

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

说明:

  • fi.getIcon().getDescription()返回的是图标原始SVG路径字符串,FontAwesome系列图标均支持该API
  • 缩放比例基于Ikonli默认的16px基准大小,可根据实际需求调整
  • 通过gc.setFill()可自定义图标颜色,效果与FontIcon的iconColor一致

内容的提问来源于stack exchange,提问作者tretonis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 15:26:22