簡體   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