views:

40

answers:

2

Hi,

I have an application that is works fine and the JFrame for it is launched in the constructor of a GameInitializer class which takes in some config parameters. I have tried to create a GUI in which allows the user to specify these config parameters and then click submit. When the user clicks submit a new GameInitializer object is created. The error I am getting is:

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.view.HumanView.update(HumanView.java:43)

once submit is called this code is executed:

values assigned to parames...   
    new GameInitializer(userName, player, Constants.BLIND_STRUCTURE_FILES.get(blindStructure), handState);

Then code in the GameInitializer constructor is:

public GameInitializer(String playerName, AbstractPlayer opponent, String blindStructureConfig, AbstractHandState handState){
        beginGame(playerName, opponent, blindStructureConfig, handState);
    }

    public static void beginGame(String playerName, AbstractPlayer opponent, String blindStructureConfig, AbstractHandState handState){
        AbstractDealer dealer;
        BlindStructure.initialize(blindStructureConfig);
        AbstractPlayer humanPlayer = new HumanPlayer(playerName, handState);

        AbstractPlayer[] players = new AbstractPlayer[2];
        players[0] = humanPlayer;
        players[1] = opponent;

        handState.setTableLayout(players);

        for(AbstractPlayer player : players){
            player.initialize();
        }

        dealer = new Dealer(players, handState);

        dealer.beginGame();
    }

It basically cascades down and eventually calls this piece of code in the HumanView class:

public void update(final Event event, final ReadableHandState handState, final AbstractPlayer player) {
        try {
            SwingUtilities.invokeAndWait(new Runnable() {

                public void run() {
                    gamePanel.update(event, handState, player);
                    validate();
                }
            });
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        if(event.equals(Event.HAND_ENDING)){
            try {
                if(handState.wonByShowdown() || handState.isSplitPot()){
                    Thread.sleep(3500);
                }
                else{
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

Do you have any idea why?

+2  A: 

The point of invokeAndWait() is for another thread to wait for something to be done in the event dispatching thread (EDT). Since this code is already executing on the EDT, it's sufficient to call it directly rather than creating a Runnable.

So this code should not be surrounded by anything:

gamePanel.update(event, handState, player); 
validate(); 
Michael Myers
+2  A: 

It looks like you're already in the Swing thread, so you're asking the Swing thread to wait while you do code in the Swing thread. This won't work. You need to remove the code surrounding

                gamePanel.update(event, handState, player);
                validate();
Chris Dennett
Good idea; I wish I'd thought of that. :P
Michael Myers
I was actually in the middle of writing the answer when I posted and saw yours :)
Chris Dennett