2

我的图形用户界面有一个奇怪的行为。首先这里有一段代码:

/**
 * 
 */
@Override
protected Void doInBackground() throws Exception {
    final ModelGameState actualGameState = controller.getActualGameState();
    final ModelCoinState actualCoinState = (actualGameState.getPlayersTurn() == ModelConstants.PLAYER_ONE_ID? actualGameState.getCoinsPlayerOne() : actualGameState.getCoinsPlayerTwo());
    final List<ModelCoinState> temp = MoveCalculator.getMoves(actualCoinState, this.cellID);
    final CountDownLatch lock = new CountDownLatch(temp.size());
    int time = 500;
    
    for(int i = 0; i < temp.size(); i++) {
        final int index = i;
        
        Timer timer = new Timer(time, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if(actualGameState.getPlayersTurn() == ModelConstants.PLAYER_ONE_ID) {
                    actualGameState.setCoinsPlayerOne(temp.get(index));
                } else {
                    actualGameState.setCoinsPlayerTwo(temp.get(index));
                }

                controller.setActualGameState(new ModelGameState(actualGameState));
                
                lock.countDown();
            }
        });
        
        timer.setRepeats(false);
        timer.start();
        
        time += 500;
    }
    
    lock.await();

    return null;
}

在第二这里我的gui:

在此处输入图像描述

这里是我的问题:每次调用 lock.await 我的屏幕看起来像这样:

在此处输入图像描述

如您所见,在我的每个圆圈后面,每次调用 lock.await() 时都会显示我的 gui 的左上角(至少我认为它是在调用 lock.await() 时,因为当我删除 lock.await( ) 我看不到我的 gui 的整个动画,但我也看不到这种奇怪的行为,并且当程序通过 doInBackground() 的所有代码时,这种行为总是出现。

是什么导致了这种奇怪的行为?

4

1 回答 1

2

不是答案,只是不同意,我的评论反对,没有评论,没有尝试过你的代码,向我道歉,有任何理由,也许是我的错

  • doInBackground() 是 AWT/Swing EDT 和 Workers Thread(s) 之间的桥梁,默认情况下从不通知 EDT

  • 处理、发布、setProgress 和 done() 通知 EDT

  • 那么 doInBackground() 中的 Swing Timer 是违背所有意图的,为什么 SwingWorker 是在官方 API 中实现的,有地方执行长时间运行的硬代码或非安全代码

  • SwingWorker 再次被指定为 AWT/Swing 和 Workers Thread(s) 之间的桥梁

    __ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ __

有两种方法

  • 将 CountDownLatch 与 invokeLater() 或 Swing Timer 一起使用。不要将它们混合在一起,也不要来自 SwingWorker

  • 使用 CountDownLatch、util.Timer、SheduledExecutor 并通过包装通知 EDT(仅相关,仅输出,方法将在屏幕上重绘) Swing 方法到 invokeLater()

  • 仅使用 Swing Timer(非准确时间段)

于 2013-08-17T15:12:36.167 回答