【发布时间】:2021-08-27 09:41:10
【问题描述】:
我在 Ubuntu 20.04 上使用 OpenJavaFX。我想让用户按下退出键来切换菜单的显示。由于帧速率非常高,我正在努力实现这一目标。
简单的程序:
class
AutoScalingCanvas extends Region {
private final Canvas canvas;
public AutoScalingCanvas(double canvasWidth, double canvasHeight) {
this.canvas = new Canvas(canvasWidth, canvasHeight);
getChildren().add(canvas);
}
public GraphicsContext getGraphicsContext2D() {
return canvas.getGraphicsContext2D();
}
@Override
protected void layoutChildren() {
double x = getInsets().getLeft();
double y = getInsets().getTop();
double w = getWidth() - getInsets().getRight() - x;
double h = getHeight() - getInsets().getBottom() - y;
// preserve aspect ratio while also staying within the available space
double sf = Math.min(w / canvas.getWidth(), h / canvas.getHeight());
canvas.setScaleX(sf);
canvas.setScaleY(sf);
positionInArea(canvas, x, y, w, h, -1, HPos.CENTER, VPos.CENTER);
}
}
public class
Gui extends Application
{
long target_ns_per_frame = 1_000_000_00 / 60;
boolean in_menu;
boolean esc_down;
@Override
public void
start(Stage primary_stage) throws Exception
{
primary_stage.setTitle("GUI");
AutoScalingCanvas canvas = new AutoScalingCanvas(1280, 720);
Scene scene = new Scene(canvas);
scene.setFill(Color.BLACK);
primary_stage.setScene(scene);
GraphicsContext gc = canvas.getGraphicsContext2D();
scene.setOnKeyPressed(new EventHandler<KeyEvent>(){
@Override
public void handle(KeyEvent event)
{
esc_down = (event.getCode() == KeyCode.ESCAPE);
}
});
scene.setOnKeyReleased(new EventHandler<KeyEvent>(){
@Override
public void handle(KeyEvent event)
{
if (event.getCode() == KeyCode.ESCAPE)
{
esc_down = false;
}
}
});
new AnimationTimer()
{
@Override
public void
handle(long total_elapsed_time_ns)
{
gc.setFill(Color.WHITE);
gc.fillRect(0, 0, 1280, 720);
if (esc_down)
{
in_menu = !in_menu;
}
if (in_menu)
{
gc.setFill(Color.BLUE);
gc.fillRect(300, 300, 200, 200);
}
else
{
gc.setFill(Color.RED);
gc.fillRect(100, 100, 100, 100);
}
long elapsed_time_ns = System.nanoTime() -
total_elapsed_time_ns;
if (elapsed_time_ns < target_ns_per_frame)
{
long time_remaining_ms = (target_ns_per_frame - elapsed_time_ns)
/ 1000;
try {
Thread.sleep(time_remaining_ms);
}
catch (InterruptedException e)
{
}
}
}
}.start();
primary_stage.show();
}
}
如果在没有Thread.sleep() 的情况下运行,帧速率约为 600fps。结果,按一次退出键将被视为向下数帧(由于我的人手指的速度限制),从而多次触发切换。这显然不是故意的。因此,我尝试将帧速率限制在 60fps。但是,随着睡眠,程序运行很慢(也许我睡错了线程?)
如何最好地跟踪输入以实现这种切换行为?
【问题讨论】:
-
我想我在这里遗漏了一些东西。想要的行为仅仅是让用户每次按下退出键时显示或隐藏菜单吗?
-
(删除了多线程标签,因为代码或问题中没有多线程。)
标签: javafx user-input frame-rate game-loop