Mic*_*rry 3 java javafx javafx-2
我有一段代码用于截取JavaFX中的节点的屏幕截图:
public BufferedImage getSnapshot(final Node... hideNodes) {
Window window = getScene().getWindow();
Bounds b = localToScene(getBoundsInLocal());
int x = (int) Math.round(window.getX() + getScene().getX() + b.getMinX());
int y = (int) Math.round(window.getY() + getScene().getY() + b.getMinY());
int w = (int) Math.round(b.getWidth());
int h = (int) Math.round(b.getHeight());
try {
Robot robot = new Robot();
for(Node node : hideNodes) {
node.setOpacity(0);
node.getParent().requestLayout();
}
BufferedImage image = robot.createScreenCapture(new java.awt.Rectangle(x, y, w, h));
for(Node node : hideNodes) {
node.setOpacity(1);
node.getParent().requestLayout();
}
return image;
}
catch(AWTException ex) {
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
它有一个扭曲,那就是它应该在截取之前隐藏给定的节点(如果它们与节点重叠,在某些情况下是明确的.)
然而,在拍摄截图之前,我很难找到一种方法来强制重绘以包含不透明度变化 - 我发现的唯一参考是requestLayout(),但没有喜悦.
我应该调用什么方法强制并等待重绘完成?
我觉得你的代码很奇怪:
node.setOpacity(0)要使它看不见,而不是node.setVisible(false)? BufferedImage而不是JavaFX Image? 也许这些事情有理由我不明白,但我只是这样做:
public Image takeSnapshot(Scene scene, final Node... hideNodes) {
for (Node node: hideNodes) node.setVisible(false);
Image image = scene.snapshot(null);
for (Node node: hideNodes) node.setVisible(true);
return image;
}
Run Code Online (Sandbox Code Playgroud)
我创建了一个使用上述例程的小样本应用程序.
主窗口包括具有圆和矩形的组.发出快照命令时,矩形隐藏在主要模式中,拍摄主要快照,然后再次在主要模式中显示矩形.

要回答关于强制UI更新的问题标题 - 你真的不能.JavaFX应用程序线程和JavaFX呈现线程将被视为两个独立的事物.您需要做的是在JavaFX应用程序线程上运行处理,将控制权返回到JavaFX系统,等待它进行渲染,然后检查结果.该scene.snapshot方法将为您处理同步,因此您不必担心它.
无论出于何种原因,scene.snapshot如果不适合您,并且您希望保留与原始策略类似的内容,那么您要做的是:
Platform.runLater呼叫并在runLater正文中获取机器人快照.Platform.runLater命令以重新获得JavaFX应用程序线程.这应该工作,因为它将允许JavaFX系统执行另一个脉冲,在机器人实际拍摄快照之前执行不透明度更改的屏幕渲染布局.另一种机制是使用JavaFX AnimationTimer,它会在JavaFX脉冲发生时为您提供回调.在AWT和JavaFX线程之间保持所有这些的正确同步将是令人讨厌的.
| 归档时间: |
|
| 查看次数: |
2610 次 |
| 最近记录: |