[英]Stop screen tearing with JavaFX AnimationTimer
In JavaFX, it seems appropriate to me to use AnimationTimer for frequently updating Canvas Nodes; 在JavaFX中,使用AnimationTimer频繁更新Canvas节点对我来说似乎很合适。 that is, for rasterized animations instead of vector animations. 也就是说,用于光栅化动画而不是矢量动画。 I'm running into an issue, which may be VSync related. 我遇到了一个问题,可能与VSync有关。 I have a singular Canvas on my Scene which contains 2D data that changes frequently (the rest of the program is done with Nodes). 我的场景上有一个单一的Canvas,其中包含频繁更改的2D数据(程序的其余部分由Nodes完成)。 I tend to get a tearing down the middle of the screen when I do this, which implies that the AnimationTimer may be falling out of sync with the monitor refresh rate. 当我这样做时,我倾向于在屏幕中间撕裂,这意味着AnimationTimer可能与监视器刷新率不同步。
This (simplified) code shows the error in detail. 此(简化的)代码详细显示了错误。 Note that I have no idea whether it's display hardware dependent, and the exact position of the tear may shift slightly. 请注意,我不知道它是否取决于显示硬件,并且撕裂的确切位置可能会略有偏移。
import javafx.application.*;
import javafx.animation.*;
import javafx.scene.*;
import javafx.scene.canvas.*;
import javafx.stage.*;
import javafx.event.*;
import javafx.scene.input.*;
import javafx.scene.paint.*;
public class BugDemo extends Application {
public static void main(String...args) {
launch(args);
}
private Canvas background = new Canvas();
private Color bgColor = Color.rgb(0, 0, 0);
@Override
public void start(Stage primaryStage) throws Exception {
Group root = new Group();
startLoops(root);
Scene scene = new Scene(root);
initUserControls(scene);
background.widthProperty().bind(scene.widthProperty());
background.heightProperty().bind(scene.heightProperty());
root.getChildren().add(background);
primaryStage.setScene(scene);
primaryStage.setTitle("Bug Demo");
primaryStage.setMaximized(true);
primaryStage.show();
}
/**
* Initializes all running control managers for game field
* @param scene primary scene of game
*/
protected void initUserControls(Scene scene) {
EventHandler<MouseEvent> handler = new EventHandler<MouseEvent>(){
@Override
public void handle(MouseEvent event) {
bgColor = Color.rgb((int)((event.getX() / background.getWidth()) * 255),
(int)((event.getY() / background.getHeight()) * 255),
255);
}};
scene.getRoot().setOnMouseMoved(handler);
scene.getRoot().setOnMouseDragged(handler);
}
/**
* Starts all game loops, which will at the beginning of the simulation and often for the extent
* of it.
* @param parent Root node
*/
protected void startLoops(Parent parent) {
GraphicsContext gc = background.getGraphicsContext2D();
new AnimationTimer() {
@Override
public void handle(long now) {
drawBackground(gc);
}}.start();
}
protected void drawBackground(GraphicsContext gc) {
gc.setFill(bgColor);
gc.fillRect(0, 0, background.getWidth(), background.getHeight());
}
}
Moving the mouse cursor over the scene will cause the canvas to shift in background color. 将鼠标光标移到场景上将导致画布的背景色发生变化。 As you move the mouse, you will notice (presumably) a tearing in the frame. 当您移动鼠标时,您会发现(大概)框架有裂痕。
It is quite possible that I'm simply being a N00B at JavaFX, and there's a perfectly friendly .sync()-ish method I'm supposed to call somewhere; 我很可能只是在JavaFX上成为N00B,而我应该在某个地方调用一个非常友好的.sync()-ish方法; but I haven't found it yet. 但是我还没有找到。 I've found bugs submitted to Oracle that look similar to this. 我发现提交给Oracle的错误看起来与此类似 。 My answer may simply be dodging using Canvas and AnimationTimer for animations. 我的答案可能只是使用Canvas和AnimationTimer来躲避动画。 All the same, even if there isn't a solution at this time, if someone has a workaround, I would love to hear about it! 都一样,即使目前没有解决方案,如果有人有解决方法,我也很想听听!
Thanks! 谢谢!
Found the issue (thank you to @VGR for pointing out the lack of system behavioral congruity)! 找到了问题(感谢@VGR指出缺少系统行为一致性)! Seems that it wasn't Java at all; 似乎根本不是Java。 it was Marco. 是马可。 I switched Desktop Windowing Managers, to Compiz specifically; 我将桌面窗口管理器专门切换为Compiz。 and the tearing is now gone. 现在眼泪已经消失了。
Evidently this isn't a bug in Java at all; 显然,这根本不是Java中的错误。 it's a trade-off for using Marco. 这是使用Marco的权衡。 This is a relief! 这是一种解脱!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.