Java 如何在接受下一个MouseeEvent之前等待当前MouseeEventHandler结束?

Java 如何在接受下一个MouseeEvent之前等待当前MouseeEventHandler结束?,java,javafx,event-handling,javafx-2,mouseevent,Java,Javafx,Event Handling,Javafx 2,Mouseevent,在我的棋盘游戏中取得进展,因此,只需单击鼠标,就会执行一些任务,如播放一些动画、接收棋盘的新窗格(我问了这个问题,我的最后一个问题,现在效果很好)、更改玩家数据等 这是我的事件处理程序 grid.setOnMouseReleased(new EventHandler<MouseEvent> () { public void handle(MouseEvent me) { //make changes to player data //recei

在我的棋盘游戏中取得进展,因此,只需单击鼠标,就会执行一些任务,如播放一些动画、接收棋盘的新窗格(我问了这个问题,我的最后一个问题,现在效果很好)、更改玩家数据等

这是我的事件处理程序

grid.setOnMouseReleased(new EventHandler<MouseEvent> () {
    public void handle(MouseEvent me) {
        //make changes to player data
        //receive new panes for the board
        //make some gui changes
        //play some animations
    }
});
但是如果我使用线程(不知道为什么,我用许多不同的方法测试了它,总是无法进行GUI更改),那么GUI更改就不会发生,所以我想这是行不通的

那么,在处理一个鼠标事件时,我能做些什么来避免任何鼠标点击呢?我认为这个问题不需要更多的代码,但如果有必要,我会编辑并添加一些代码

编辑:

所以我制作了一个动画类数组,因为我需要很多这样的窗格,并且需要跟踪每一个窗格

当我需要播放动画时,我调用
playAnimation()
方法

现在,这个
playAnimation()
方法就像一个动画开始

此窗格上的动画完成后,将根据玩家的进度对棋盘进行更改,如果需要。。。此
playAnimation()
方法将调用几个其他动画对象的
playAnimation()
方法

grid.setOnMouseReleased(new EventHandler<MouseEvent> () {
    public void handle(MouseEvent me) {
        //make changes to player data
        //receive new panes for the board
        //make some gui changes
        //play some animations
        someAnimationObject.playAnimation();
    }
});
最后,我按照Brad的建议,在MouseEvent事件处理程序中使用了
anyAnimating
的值作为标志

grid.setOnMouseReleased(new EventHandler<MouseEvent> () {
    public void handle(MouseEvent me) {
        if(!anyAnimating.get()){
            //make changes to player data
            //receive new panes for the board
            //make some gui changes
            //play some animations
        }
    } 
});
grid.setOnMouseReleased(新的EventHandler(){
公共无效句柄(MouseEvent me){
如果(!anyAnimating.get()){
//更改播放器数据
//接收董事会的新窗格
//进行一些gui更改
//播放一些动画
}
} 
});

我认为这可以通过两种不同的方式来处理。想到的一种方法是使用一个简单的信号量。要做到这一点,只需在类的顶部声明一个名为isupdate的布尔字段

private boolean isUpdating = false;
当您输入鼠标单击时,该方法要做的第一件事是检查IsUpdate是否为false。如果是这样的话,下一步就是将isupdate设置为true,执行该操作,然后再次将其设置为false

grid.setOnMouseReleased(new EventHandler<MouseEvent> () {
    public void handle(MouseEvent me) {
        if(!isUpdating){
            isUpdating = true;
            //make changes to player data
            //receive new panes for the board
            //make some gui changes
            //play some animations
            isUpdating = false;
        }
    } 
});
工作线程:

grid.setOnMouseReleased(new EventHandler<MouseEvent> () {
 public void handle(MouseEvent me) {
        Thread t = new Thread(new Runnable() {
            public void run() {
                //completing the necessary tasks here
                refresh();
            }
        });
        t.start();
        t.join();
    }
});
然后将侦听器添加到需要访问的对象:

public class MyUIClass() {
    private List<GridListener> listeners;

}

public MyUIClass(){
    listeners = new ArrayList<GridListener>();
}

public void addListener(GridListener listener) {
    listeners.add(listener);
}
public类MyUIClass(){
私人名单听众;
}
公共MyUIClass(){
侦听器=新的ArrayList();
}
公共void addListener(GridListener侦听器){
添加(侦听器);
}

这可能比您想编写的代码要多,以解决您当前的问题,这些只是我在阅读您的问题时想到的一些建议。

我不太确定这里的细节,因为您的问题中没有太多关于如何管理动画的细节,但这应该能让您大致了解

动画
类添加一个标志,指示动画是否正在进行:

class Animations {

    private ReadOnlyBooleanWrapper animating = new ReadOnlyBooleanWrapper() ;

    public ReadOnlyBooleanProperty animatingProperty() {
        return animating.getReadOnlyProperty();
    }

    public boolean isAnimating() {
        return animatingProperty().get();
    }

    public Pane getAnimationPane() {
        //returns Pane which would be used for transition
    }

    public void playAnimation() {
        //called only when the timeline transition is to be played

        Animation animation = ... ;
        animation.statusProperty().addListener((obs, oldStatus, newStatus) -> 
            animating.set(newStatus == Animation.Status.RUNNING));

        animation.play(); // etc


    }
}
现在你可以做了

grid.setOnMouseReleased(new EventHandler<MouseEvent> () {
    public void handle(MouseEvent me) {

        if (! someAnimationObject.isAnimating()) {
            //make changes to player data
            //receive new panes for the board
            //make some gui changes
            //play some animations
            someAnimationObject.playAnimation();
        }
    }
});
然后,事件处理代码可以执行以下操作:

// declared at instance level:
private boolean animating = false ;

grid.setOnMouseReleased(new EventHandler<MouseEvent> () {
    public void handle(MouseEvent me) {
        if (! animating) {
            animating = true ;
            //make changes to player data
            //receive new panes for the board
            //make some gui changes
            //play some animations
            someAnimationObject.playAnimation( () -> {animating = false ;});
        }
    }
});
//在实例级别声明:
私有布尔动画=false;
setOnMouseReleased(新的EventHandler(){
公共无效句柄(MouseEvent me){
如果(!设置动画){
动画=真;
//更改播放器数据
//接收董事会的新窗格
//进行一些gui更改
//播放一些动画
播放动画(()->{animating=false;});
}
}
});

grid.setOnMouseReleased(新的EventHandler(){
公共无效句柄(MouseEvent me){
grid.setDisable(true);
//更改播放器数据
//接收董事会的新窗格
//进行一些gui更改
//播放一些动画
播放动画(()->{grid.setDisable(false);});
}
});

哇,这么多解决方案,我会尝试一下,然后告诉你。我尝试了第一个,布尔值更新。布尔值将在任务完成之前更改,因此它对我不起作用。带有线程的解决方案不起作用。您不应该从FX应用程序线程调用
join()
:它将阻止FX应用程序线程上的执行,并阻止更新UI。另外,
revalidate()
repaint()
是JavaFXAPI中不存在的方法。哦,这是我的错误-我没有意识到问题在于JavaFX。AWT/Swing也会出现同样的问题:你不能阻止事件分派线程。哦,对了,我同意这一点。事实上,我甚至没有注意到有一个加入,直到你提到它。但是关于重新验证和重新绘制,我知道它们在JavaFX中不存在,但我还不太熟悉JavaFXUI框架,所以我无法对正确的方式发表评论。。。我只同意我的建议是无效的。你能更详细地介绍一下你是如何启动动画的吗?如果动画正在运行,您不需要在处理程序中执行任何操作,您可以通过检查动画的
状态
属性来执行该操作。@James\u D,提供了更多的信息说实话,如果我给出有关如何管理动画的代码,那么这个问题将增加近250行。关于你的回答,我到现在还没有使用过听众。假设我在示例中使用的
someAnimationObject
对另外10个动画对象调用
playAnimation()
。在EventHandler中,我们仅为
someAnimationObject
检查
isNowAnimating
,如果其他对象仍在动画中呢?它还能工作吗?不,您需要确保只有在完成所有操作后,才将属性设置为false。(例如,它可以注册自己的侦听器)。如果您使用的是
paralleltransformation
和/或
SequentialTransition
,那么它应该很简单(只需将状态侦听器注册为代表整个thi的“大”转换即可)
public interface GridListener {
    public void gridUpdated();
}
public class MyUIClass() {
    private List<GridListener> listeners;

}

public MyUIClass(){
    listeners = new ArrayList<GridListener>();
}

public void addListener(GridListener listener) {
    listeners.add(listener);
}
class Animations {

    private ReadOnlyBooleanWrapper animating = new ReadOnlyBooleanWrapper() ;

    public ReadOnlyBooleanProperty animatingProperty() {
        return animating.getReadOnlyProperty();
    }

    public boolean isAnimating() {
        return animatingProperty().get();
    }

    public Pane getAnimationPane() {
        //returns Pane which would be used for transition
    }

    public void playAnimation() {
        //called only when the timeline transition is to be played

        Animation animation = ... ;
        animation.statusProperty().addListener((obs, oldStatus, newStatus) -> 
            animating.set(newStatus == Animation.Status.RUNNING));

        animation.play(); // etc


    }
}
grid.setOnMouseReleased(new EventHandler<MouseEvent> () {
    public void handle(MouseEvent me) {

        if (! someAnimationObject.isAnimating()) {
            //make changes to player data
            //receive new panes for the board
            //make some gui changes
            //play some animations
            someAnimationObject.playAnimation();
        }
    }
});
grid.setOnMouseReleased(new EventHandler<MouseEvent> () {
    public void handle(MouseEvent me) {

        grid.setDisable(true);

        //make changes to player data
        //receive new panes for the board
        //make some gui changes
        //play some animations
        someAnimationObject.animatingProperty().addListener((obs, wasAnimating, isNowAnimating) -> {
            if (! isNowAnimating) {
                grid.setDisable(false);
            }
        });
        someAnimationObject.playAnimation();
    }
});
class Animations {


    public Pane getAnimationPane(Runnable finishedCallback) {
        //returns Pane which would be used for transition
    }

    public void playAnimation() {
        //called only when the timeline transition is to be played

        Animation animation = ... ;
        animation.statusProperty().addListener((obs, oldStatus, newStatus) -> { 
            if (newStatus == Animation.Status.STOPPED) {
                finishedCallback.run();
            }
        });

        animation.play(); // etc


    }
}
// declared at instance level:
private boolean animating = false ;

grid.setOnMouseReleased(new EventHandler<MouseEvent> () {
    public void handle(MouseEvent me) {
        if (! animating) {
            animating = true ;
            //make changes to player data
            //receive new panes for the board
            //make some gui changes
            //play some animations
            someAnimationObject.playAnimation( () -> {animating = false ;});
        }
    }
});
grid.setOnMouseReleased(new EventHandler<MouseEvent> () {
    public void handle(MouseEvent me) {
        grid.setDisable(true);
        //make changes to player data
        //receive new panes for the board
        //make some gui changes
        //play some animations
        someAnimationObject.playAnimation( () -> {grid.setDisable(false);});

    }
});