繁体   English   中英

如何从事件处理程序向 Java FX 主线程发出信号?

[英]How to signal the Java FX main thread from an event handler?

我正在开发一个国际象棋游戏应用程序,我决定让主游戏循环等到用户选择一个字段。 为此,我制作了一个java.util.concurrent.locks.Condition object,主应用程序线程在其上等待,并且一旦用户单击某处,事件处理程序就会发出信号。

但是,单击处理程序永远不会运行,因此,整个程序被冻结,因为条件从未发出信号。 有什么方法可以确保处理程序运行,或者在主线程等待条件时不检查事件?

(几乎)最小的例子:

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

import java.util.concurrent.locks.*;

public class EventHandlerLockExample extends Application {
    public static final Lock lock = new ReentrantLock();
    public static final Condition availableClick = lock.newCondition();
    public static int x, y;

    @Override
    public void start(Stage primaryStage) throws InterruptedException{
        Canvas can = new Canvas(128, 128);
        Scene scene = new Scene(new Group(can));
        scene.setOnMouseClicked(event -> {
            lock.lock();
            try{
                x = (int) event.getSceneX();
                y = (int) event.getSceneY();
                availableClick.signal();
            }finally{
                lock.unlock();
            }
        });
        primaryStage.setTitle("Chess Game");
        primaryStage.setScene(scene);
        primaryStage.show();
        lock.lock();
        try{
            availableClick.await();
            can.getGraphicsContext2D().setFill(Color.RED);
            can.getGraphicsContext2D().fillOval(x, y, 5, 5);
            System.out.printf("Click[x=%d ,y=%d]%n", x, y);
        }finally{
            lock.unlock();
        }
    }

    public static void main(String[] args){
        launch(args);
    }
}

我建议您使用多线程将 UI、计算机和播放器分开。

JavaFX GUI 将被冻结,如果您暂停其线程,可能会导致问题(例如监听点击),所以我要做的是为计算机播放器创建一个线程,为实际播放器创建一个线程。 这样,您可以根据需要锁定/解锁这些线程,并且 GUI 不会被冻结。

要实现多线程,您可以使用以下代码:

private ScheduledExecutorService scheduledExS;
private ScheduledFuture<?>       scheduled;
/* Start thread to periodically execute getData() with 0ms starting delay every 500ms  */
scheduledExS = Executors.newScheduledThreadPool(1);
scheduled    = scheduledExS.scheduleAtFixedRate(getData, 0, 500, TimeUnit.MILLISECONDS);
/* Stop thread when finished */
scheduledExS.shutdownNow();

其中getData是可运行的 function

Runnable getData = () -> { /* Do something */ };

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM