JavaFX 截图卡死 UI 的根治 Java2D 纯数据渲染
痛点
病害导出的时候,每条病害要生成一张雷达图截图。原来的做法是直接对着界面上那个 JavaFX 节点调 snapshot() 截图。问题来了:snapshot() 必须在 FX Application Thread 上跑,导出几十上百张图的时候,主线程被这些截图任务占得死死的,整个 UI 完全卡住,进度条都不带动的。
思路
卡死的根子在于渲染绑死在 UI 线程上了。要彻底解决,就得让渲染脱离 JavaFX 节点,变成在随便哪个线程上都能跑的纯计算。所以我把截图渲染从”拍 UI”改成了”用 Java2D 拿纯数据画”。
改造
按 MVVM 三层切开:
- View 层只管从 UI 组件里抠出纯数据(当前视口的里程范围、采样值数组、增益、颜色映射这些),不掺和画图。
- ViewModel 层负责渲染的调度和参数拼装,把 View 抠出来的数据组装成绘图参数。
- Service 层是纯绘图,用
BufferedImage+Graphics2D画雷达图、层位线、病害框、信息面板,完全不碰 JavaFX。
// Service 层,任意线程可跑 |
收益
改完之后:渲染脱离了 UI 线程,可以拿协程并发跑,导出的时候 UI 一点不卡;也不依赖界面状态,哪怕雷达图窗口没开、界面尺寸不对,也能正常出图(极端情况下还能动态放大窗口或者降级渲染);速度比 snapshot() 还快,省掉了 JavaFX 渲染管线那一道中转。
遇到 UI 卡死这种事,要从根上解决,就是把耗时的渲染、计算从 UI 线程上搬走,而不是绞尽脑汁去优化 UI 线程里那点执行。在 JavaFX 下要做”后台批量出图”,Java2D 这种纯数据绘制挺好使。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CYK's Blog!
评论
