我有一个简单的应用程序,它生成基于 JavaFX 的 png 图表。该应用程序无法在无显示机器上运行,但出现以下异常,我不需要在控制台上渲染或显示内容,只需要创建图像。
"main" java.lang.UnsupportedOperationException: Unable to open DISPLAY
at com.sun.glass.ui.gtk.GtkApplication.<init>(GtkApplication.java:68)
at com.sun.glass.ui.gtk.GtkPlatformFactory.createApplication(GtkPlatformFactory.java:41)
at com.sun.glass.ui.Application.run(Application.java:146)
at com.sun.javafx.tk.quantum.QuantumToolkit.startup(QuantumToolkit.java:257)
at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:211)
at javafx.embed.swing.JFXPanel.initFx(JFXPanel.java:215)
at javafx.embed.swing.JFXPanel.<init>(JFXPanel.java:230)
我正在尝试在 AWS 实例上运行它。有办法解决这个问题吗?以下是我的示例代码。
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.embed.swing.JFXPanel;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.image.WritableImage;
import javafx.stage.Stage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import javax.imageio.ImageIO;
public class Test {
public static void main(String[] args) {
String chartGenLocation = "/Users/tmp";
new JFXPanel();
ObservableList<PieChart.Data> pieChartData =
FXCollections.observableArrayList(
new PieChart.Data("Failed", 10),
new PieChart.Data("Skipped", 20));
final PieChart chart = new PieChart(pieChartData);
chart.setAnimated(false);
Platform.runLater(() -> {
Stage stage = new Stage();
Scene scene = new Scene(chart, 500, 500);
stage.setScene(scene);
WritableImage img = new WritableImage(500, 500);
scene.snapshot(img);
File file = new File(Paths.get(chartGenLocation, "a.png").toString());
try {
ImageIO.write(SwingFXUtils.fromFXImage(img, null), "png", file);
} catch (IOException e) {
//logger.error("Error occurred while writing the chart image
}
});
}
}
我见过很少的答案,主要谈论 monocle 和 testfx,在这里我无法添加外部依赖项。所以添加 testfx 不是一个选择。我还用 xvbf 尝试了以下操作,它挂起了系统,
Xvfb :95 -screen 0 1024x768x16 &> xvfb.log &
export DISPLAY=:95.0
当我执行时,我看到以下输出并且系统挂在那里。
(process:13112): Gtk-WARNING **: Locale not supported by C library.
Using the fallback 'C' locale.
Fontconfig warning: ignoring UTF-8: not a valid region tag
更新
执行顺序
Xvfb :92 -screen 0 1024x768x16 &> xvfb.log &
export DISPLAY=:92.0
xvbf.log 中没有错误,似乎启动正常。
java Test
我在控制台输出中看到以下内容
(process:13356): Gtk-WARNING **: Locale not supported by C library.
Using the fallback 'C' locale.
Fontconfig warning: ignoring UTF-8: not a valid region tag
我在xvbf.log中没有看到任何日志,在上述日志之后执行没有继续进行。我的图像没有生成。
更新2
我想知道是否有办法绕过此验证,因为我真的不需要显示渲染。
我在使用 xvfb 作为 UI 测试的显示管理器的 Ubuntu 服务器上遇到了相同的 JavaFX 问题,对我来说根本原因是我转发的 DISPLAY 没有注入到 dbus 的激活环境中,因此 dbus 激活的任何尝试呈现 UI 的内容无法连接到显示器并导致“无法打开显示器”异常。
在启动 UI 测试之前在该 shell 中运行
dbus-update-activation-environment --systemd DISPLAY XAUTHORITY
为我解决了这个问题。
启动虚拟显示服务器解决了我的问题。
# Starting a virtual display to support FX chart generation
echo "Starting Xvfb virtual display for chart generation"
export DISPLAY=:95
nohup Xvfb :95 -screen 0 1024x768x16 > /dev/null 2>&1 &