вызов invokeAndWait от EDT

У меня есть проблема при следовании из моей предыдущей проблемы. У меня также есть код SwingUtillities.invokeAndWait где-то в другом месте в кодовой базе, но когда я удаляю это, gui не обновляется. Если я не удаляю его ошибка, я добираюсь:

Exception in thread "AWT-EventQueue-0" java.lang.Error: Cannot call invokeAndWait from the event dispatcher thread
 at java.awt.EventQueue.invokeAndWait(Unknown Source)
 at javax.swing.SwingUtilities.invokeAndWait(Unknown Source)
 at game.player.humanplayer.model.HumanPlayer.act(HumanPlayer.java:69)

Код в HumanPlayer.act:

public Action act(final Action[] availiableActions) {
  try {

   SwingUtilities.invokeAndWait(new Runnable() {
    @Override
    public void run() {
     gui.update(availiableActions);
    }
   });
  }
  catch (InterruptedException e) {
   e.printStackTrace();
  } catch (InvocationTargetException e) {
   e.printStackTrace();
  }

  synchronized(performedAction){
   while(!hasPerformedAction()){
    try {
     performedAction.wait();
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
   }
   setPerformedAction(false); 
  }

  return getActionPerfomed();
 }

Изображение потоков, когда в отладке, поскольку экран не красит: сопроводительный текст http://img684.imageshack.us/img684/6669/69288941.png

Текстовая версия стека:

ui.startup.LoginScreen at localhost:51050
 -> Deamon Thread [AWT-Windows] (Running)
 -> Thread [AWT-Shutdown] (Running)
 -> Thread [AWT-EventQueue-0] (Running)
 -> Thread [DestroyJavaVM] (Running)

6
задан Community 23 May 2017 в 11:53
поделиться

3 ответа

Ответ: вместо того, чтобы делать вызов

new GameInitializer(userName, player, Constants.BLIND_STRUCTURE_FILES.get(blindStructure), handState);

из EDT, сделайте его выполнение в новом (не EDT) потоке, чтобы позже, когда будет вызван invokeAndWait, он работал корректно, так как поток, выполняющий эту команду, не является EDT. Измененный код выглядит следующим образом:

Thread t = new Thread(new Runnable() {
    @Override
    public void run() {
       new GameInitializer(userName, player, Constants.BLIND_STRUCTURE_FILES.get(blindStructure), handState);       
    }

   });
t.start();
7
ответ дан 8 December 2019 в 18:34
поделиться

На основе комментарии, похоже, вы не перерисовываете рамку после завершения действий. Если вы этого не сделаете, то экран будет обновляться только в случайное время (возможно, когда другое окно перемещается вперед).

Внутри gui.update я предлагаю вам сделать последнюю строку:

myFrame.repaint();

(более или менее, в зависимости от ваших обстоятельств).


Редактировать: Как оказалось, настоящая проблема заключается в следующем цикле:

synchronized(performedAction){
    while(!hasPerformedAction()){
        try {
            performedAction.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    setPerformedAction(false);
}

Поскольку существует только один поток приложения (который оказывается EDT), результат hasPerformedAction () никогда не может измениться (при условии, что это простой получатель). Нет другого потока для изменения значения. Поскольку этот бесконечный цикл находится на EDT, графический интерфейс никогда не может быть перерисован; следовательно, он блокируется.

1
ответ дан 8 December 2019 в 18:34
поделиться

invokeAndWait () предназначен для вызова из потока без графического интерфейса пользователя. Он отправляет объект Runnable в поток графического интерфейса пользователя, где он будет выполнен.

Нет смысла отправлять объект Runnable из потока GUI самому себе. Это имеет тот же эффект, что и прямой вызов run () для объекта Runnable .

4
ответ дан 8 December 2019 в 18:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: