mfgravesjr
mfgravesjr

Reputation: 47

Code executes twice with invokeLater. I experience painting artifacts without it

I'm programming a simple card game. When you click on the deck of cards, it draws a card, then it's supposed to pop up with a message dialog saying it's player 2's turn. However, the card that is removed and painted into to player 1's hand, gets interrupted by the JOptionPane message dialog, and it creates an artifact (by which I mean it paints the card in the hand, but also somewhere random between the deck and your hand.) SwingUtilities.invokeLater on the AI response and JOptionPane.showMessageDialog seemed to be the logical choice, but it causes the code to execute twice, giving player 2 (an AI) two turns. Using invokeAndWait throws an error because it's being called from the EDT, so I am out of options. How would I go about getting rid of the artifact? http://i1065.photobucket.com/albums/u400/mfgravesjr/go%20fish%20screenshot_zpsxav4hn59.png

This is the mouse listener in every pile of cards. It is part of a class I've named Stack. There's an if statement in mouseReleased that sees if the card is being dragged. If it is not, it will execute StackRuleConstraints.stackClickAction(), which is defined in the next block of code down from this.

     private MouseAdapter ml = new MouseAdapter()
     {
        public void mousePressed(MouseEvent e)
        {
           targetCardTable = (CardTable)SwingUtilities.getAncestorOfClass(CardTable.class,selfReference);
           if((rules&INACCESSIBLE)==0)
           {
              if((rules&RECEPTACLE)>0)
              {
                 reasonForRejection = "This stack abides by the RECEPTACLE rule. You cannot draw cards from this pile.";
                 if(printRuleRejections)System.out.println(reasonForRejection);
                 return;
              }
              xOrigin = e.getXOnScreen();
              yOrigin = e.getYOnScreen();

              for(int i = 0; i < cards.size(); i++)
              {
                 if(cards.get(i).getLocationOnScreen().x<xOrigin
                    &&xOrigin<cards.get(i).getLocationOnScreen().x+50
                    &&cards.get(i).getLocationOnScreen().y<yOrigin
                    &&yOrigin<cards.get(i).getLocationOnScreen().y+70)
                    {
                       cardsToRemove.clear();
                       groupedCards = null;
                       if(i!=cards.size()-1)
                       {
                          if((rules&GRAB_FROM_TOP)>0)continue;
                          if((rules&GRAB_BY_GROUP)>0&&i!=cards.size()-1)
                          {
                             groupedCards = new Card[cards.size()-1-i];
                             for(int j = i+1; j < cards.size(); j++)
                             {
                                groupedCards[j-i-1] = cards.get(j);
                                cardsToRemove.add(cards.get(j));
                             }
                          }
                       }
                       if((rules&DRAW_PILE)==0&&!cards.get(i).isSelected())//if the card you clicked is facedown
                       {
                          if(i!=cards.size()-1)
                          {
                             continue; //if it's not the top card, return
                          }
                          else if((rules&FLIPPABLE)>0)//otherwise flip it faceup
                          {
                             cards.get(i).setSelected(true);
                             repaint();
                             return;
                          }
                       }
                       cardOrigin = cards.get(i).getLocationOnScreen();
                       selectedCard = cards.get(i);
                       draggedCardXOffset = xOffset;
                       draggedCardYOffset = yOffset;
                    }
              }
           }
           else
           {
              reasonForRejection = "This stack abides by the INACCESSIBLE rule. You cannot manipulate the cards in this stack.";
              if(printRuleRejections)System.out.println(reasonForRejection);
           }
        }

        public void mouseDragged(MouseEvent e)
        {
           if(!dragging&&selectedCard!=null)
           {
              remove(selectedCard);
              if(cardsToRemove.size()>0)for(int i = 0; i < cardsToRemove.size(); i++){remove(cardsToRemove.get(i));}
              dragging = true;
           }
           mouseX = e.getXOnScreen();
           mouseY = e.getYOnScreen();
           ((CardTable)SwingUtilities.getAncestorOfClass(CardTable.class,selfReference)).repaint();
        }

        public void mouseReleased(MouseEvent e)
        {
           if(dragging)ADDING_CARD_TO_STACK:
           {
              for(Component c: getParent().getComponents())
              {
                 if(c instanceof Stack
                    &&e.getXOnScreen()>c.getLocationOnScreen().x
                    &&e.getXOnScreen()<c.getLocationOnScreen().x+c.getWidth()
                    &&e.getYOnScreen()>c.getLocationOnScreen().y
                    &&e.getYOnScreen()<c.getLocationOnScreen().y+c.getHeight()
                    &&selectedCard!=null)
                    {
                       if((((Stack)c).rules&DRAW_PILE)>0)
                       {
                          reasonForRejection = "This stack abides by the DRAW_PILE rule. You cannot place a card here.";
                          if(printRuleRejections)System.out.println(reasonForRejection);
                          break;
                       }
                       if((((Stack)c).rules&INACCESSIBLE)>0)
                       {
                          reasonForRejection = "This stack abides by the INACCESSIBLE rule. You cannot manipulate the cards in this stack.";
                          if(printRuleRejections)System.out.println(reasonForRejection);
                          break;
                       }
                       if((((Stack)c).rules&AUTO_FACEUP)==0&&!selectedCard.isSelected())
                       {
                          reasonForRejection = "This stack does not abide by the AUTO_FACEUP rule. Cards placed on this stack must be faceup.";
                          if(printRuleRejections)System.out.println(reasonForRejection);
                          break;
                       }
                       if((((Stack)c).rules&ASCENDING)>0&&(((Stack)c).cards.size()>0&&((Stack)c).cards.get(((Stack)c).cards.size()-1).getRank()!=selectedCard.getRank()-1)||(((Stack)c).cards.size()==0&&selectedCard.getRank()!=1&&(((Stack)c).rules&ASCENDING)>0))
                       {
                          reasonForRejection = "This stack abides by the ASCENDING rule. Cards placed on this pile must have a rank equal to one plus the rank of the card below it.";
                          if(printRuleRejections)System.out.println(reasonForRejection);
                          break;
                       }

                       if(((((Stack)c).rules&DESCENDING)>0&&((Stack)c).cards.size()>0&&((Stack)c).cards.get(((Stack)c).cards.size()-1).getRank()!=selectedCard.getRank()+1)||(((Stack)c).cards.size()==0&&selectedCard.getRank()!=13&&(((Stack)c).rules&DESCENDING)>0))
                       {
                          reasonForRejection = "This stack abides by the DESCENDING rule. Cards placed on this pile must have a rank equal to the rank of the card below it, minus one.";
                          if(printRuleRejections)System.out.println(reasonForRejection);
                          break;
                       }
                       if((((Stack)c).rules&SAME_SUITS)>0&&(((Stack)c).cards.size()>0&&((Stack)c).cards.get(((Stack)c).cards.size()-1).getSuit()!=selectedCard.getSuit()))
                       {
                          reasonForRejection = "This stack abides by the SAME_SUITS rule. Cards played on this stack must have the same suit as the card below it.";
                          if(printRuleRejections)System.out.println(reasonForRejection);
                          break;
                       }
                       if((((Stack)c).rules&ALTERNATING_COLORS)>0&&(((Stack)c).cards.size()>0&&((Stack)c).cards.get(((Stack)c).cards.size()-1).getColor()==selectedCard.getColor()))
                       {
                          reasonForRejection = "This stack abides by the ALTERNATING_COLORS rule. Cards played on this stack must have a different color than the card below it.";
                          if(printRuleRejections)System.out.println(reasonForRejection);
                          break;
                       }
                       if(ruleConstraints!=null)if(ruleConstraints.restrictedTo.size()>0)if((rules&RESTRICTED_STACK)>0&&!ruleConstraints.restrictedTo.contains((Stack)c))
                       {
                          reasonForRejection = "The stack you drew this card from abides by the RESTRICTED_STACK rule. The stack you are playing this card on is not contained within the restrictedTo list from the StackRuleConstraints object.";
                          if(printRuleRejections)System.out.println(reasonForRejection);
                          break;
                       }
                       if(((Stack)c).ruleConstraints!=null)if(((Stack)c).ruleConstraints.restrictedFrom.size()>0)if((((Stack)c).rules&RESTRICTED_STACK)>0&&!((Stack)c).ruleConstraints.restrictedFrom.contains(selfReference))
                       {
                          reasonForRejection = "This stack abides by the RESTRICTED_STACK rule. The stack you drew from is not contained within this stack's restrictedFrom list from the StackRuleConstraints object.";
                          if(printRuleRejections)System.out.println(reasonForRejection);
                          break;
                       }

                       ((Stack)c).add(selectedCard);
                       if(groupedCards!=null)for(Card card: groupedCards)((Stack)c).add(card);
                       if((((Stack)c).rules&STACK_ACTION)>0&&((Stack)c).ruleConstraints!=null){((Stack)c).ruleConstraints.stackDropAction();}
                       break ADDING_CARD_TO_STACK;
                    }
              }
              if(dragging&&selectedCard!=null){add(selectedCard);if(groupedCards!=null)for(Card card: groupedCards)add(card);}
           }
           else 
           {
              if((rules&INACCESSIBLE)==0)
              {
                 if((rules&DRAW_PILE)>0&&ruleConstraints!=null)
                 {
                    if(ruleConstraints.recyclePile!=null)
                    {  
                       if(cards.size()==0&&(ruleConstraints.recyclePile.rules&RECYCLABLE)>0)
                       {
                          for(int i = ruleConstraints.recyclePile.cards.size()-1; i >= 0; i--)
                          {
                             Card c = ruleConstraints.recyclePile.cards.get(i);
                             c.setSelected(false);
                             add(c);
                          }
                          ruleConstraints.recyclePile.cards.clear();
                       }
                    }
                    else
                    {
                       reasonForRejection = "This stack abides by the RECYCLABLE rule, but does not have a recycle pile set up to do that.";
                       if(printRuleRejections)System.out.println(reasonForRejection);
                    }
                    if(ruleConstraints.dropPile!=null)
                    {
                       if(cards.size()>0)
                       {
                          if(selectedCard!=null)selectedCard.setSelected(true);
                          else return;
                          dealTo(selectedCard,ruleConstraints.dropPile,true);
                          // remove(selectedCard);
  //                         ruleConstraints.dropPile.add(selectedCard);
                       }
                    }
                    else
                    {
                       reasonForRejection = "This stack abides by the DROP_PILE rule, but does not have a StackRuleConstraints dropPile set up to do that.";
                       if(printRuleRejections)System.out.println(reasonForRejection);
                    }
                 }

                 if((rules&STACK_ACTION)>0&&ruleConstraints!=null)ruleConstraints.stackClickAction();
              }
              else
              {
                 reasonForRejection = "This stack abides by the INACCESSIBLE rule. You cannot manipulate the cards in this stack.";
                 if(printRuleRejections)System.out.println(reasonForRejection);
              }
           }
           selectedCard = null;
           groupedCards = null;
           cardsToRemove.clear();
           dragging = false;

           targetCardTable = (CardTable)SwingUtilities.getAncestorOfClass(CardTable.class,selfReference);
           targetCardTable.repaint();
           if(!targetCardTable.isGameOver())
           {
              if(targetCardTable.isGameWon()){targetCardTable.performGameWonAction();targetCardTable.endGame();}
              if(targetCardTable.isGameLost()){targetCardTable.performGameLostAction();targetCardTable.endGame();}
           }
        }
     };

This is the constructor of my GoFish game.

  public GoFish()
  {
     super("Go Fish");
     inquireDialog.setLayout(new GridBagLayout());
     JPanel pnl = new JPanel();
     pnl.setLayout(new GridBagLayout());
     GridBagConstraints gbc = new GridBagConstraints();
     gbc.anchor = gbc.CENTER;
     gbc.weightx = 1;
     gbc.gridy = 1;
     gbc.gridx = 1;
     gbc.gridwidth = 2;
     gbc.insets = new Insets(10,10,10,10);
     pnl.add(spinnerLbl,gbc);
     gbc.gridx = 1;
     gbc.gridwidth = 1;
     gbc.gridy = 2;
     gbc.anchor = gbc.EAST;
     spinner.setPreferredSize(new Dimension(spinner.getPreferredSize().width+15,spinner.getPreferredSize().height));
     tf = ((JSpinner.DefaultEditor)spinner.getEditor()).getTextField();
     tf.setEditable(false);
     tf.addKeyListener(ka);
     pnl.add(spinner,gbc);
     gbc.gridx = 2;
     gbc.anchor = gbc.WEST;
     pnl.add(inquireButton,gbc);
     inquireButton.addActionListener(this);
     inquireDialog.add(pnl);
     inquireDialog.setSize(400,150);
     WindowPositioner.setLocation(inquireDialog,WindowPositioner.CENTER,false);
     inquire.add(inquireLbl);
     inquire.addActionListener(this);
     ws = getWorkspace();
     ws.setLayout(new BorderLayout());
     player1PairLbl.setForeground(Color.WHITE);
     player2PairLbl.setForeground(Color.WHITE);
     player1SidePnl.setLayout(new BorderLayout());
     player2SidePnl.setLayout(new BorderLayout());
     centerPnl.setLayout(new GridBagLayout());
     player2Hand.setStackRules(Stack.INACCESSIBLE);
     src = new StackRuleConstraints()
     {
        public void stackClickAction()
        {
           // SwingUtilities.invokeLater(new Runnable(){public void run(){

              deck.setStackRules(Stack.INACCESSIBLE);
              if(player1Hand.cards.get(player1Hand.cards.size()-1).getRankText().equals(inquireText))
              {
                 inquire.setEnabled(true);
                 player1Hand.setStackRules(player1HandStackRules);
              }
              else
              {
                 status.setStatus("Player 2's turn.");
                 JOptionPane.showMessageDialog(null,"Player 2's turn.");
                 while(true)
                 {
                    for(int rank = 1; rank <= 13; rank++)
                    {
                       int cardCount = 0;
                       Card[] pair = new Card[2];
                       for(Card c: player2Hand.cards)
                       {
                          if(c.getRank()==rank)cardCount++;
                       }
                       if(cardCount>=2)
                       {
                          int i = 0;
                          for(Card c: player2Hand.cards)
                          {
                             if(c.getRank()==rank){pair[i] = c;i++;}
                             if(i==2){for(Card c2: pair)player2Hand.dealTo(c2,playStack2,true);break;}
                          }
                       }
                    }
                    if(isGameWon())performGameWonAction();
                    if(isGameLost())performGameLostAction();
                    if(isGameWon()||isGameLost())endGame();
                    if(isGameOver()) return;
                    //EASY
                    if(difficultySetting==0)try{
                    String cardInquiry = player2Hand.cards.get(new Random().nextInt(player2Hand.cards.size())).getRankText();
                    JOptionPane.showMessageDialog(null,"Player 2 is fishing for "+cardInquiry+(cardInquiry.equals("Six")?"e":"")+"s.");
                    CHECKING:
                    {
                       for(int i = 0; i < player1Hand.cards.size(); i++)
                       {
                          if(player1Hand.cards.get(i).getRankText().equals(cardInquiry)){player1Hand.dealTo(player1Hand.cards.get(i),player2Hand,false);break CHECKING;}
                       }
                       deck.dealTo(player2Hand,false);
                       if(!player2Hand.cards.get(player2Hand.cards.size()-1).getRankText().equals(cardInquiry))
                       {
                          status.setStatus("Player 1's turn.");
                          inquire.setEnabled(true);
                          player1Hand.setStackRules(player1HandStackRules);
                          JOptionPane.showMessageDialog(null,"Player 1's turn.");
                          return;
                       }
                    }}
                    catch(IllegalArgumentException e){}
                    //NORMAL
                    else if(difficultySetting==1)
                    {
                       int player2AskCount=Integer.MAX_VALUE;
                       int player1AskCount=0;
                       int player1MaximumCardIndex = -1;
                       int player2MinimumCardIndex = -1;
                       for(int i = 1; i <= 13; i++)
                       {
                          for(Card c: player2Hand.cards)
                          {
                             if(Card.getRankText(i).equals(c.getRankText())&&player1CardTracker[i]>player1AskCount)
                             {
                                player1AskCount = player1CardTracker[i];
                                player1MaximumCardIndex = i;
                             }
                             if(Card.getRankText(i).equals(c.getRankText())&&player2CardTracker[i]<player2AskCount)
                             {
                                player2AskCount = player2CardTracker[i];
                                player2MinimumCardIndex = i;
                             }
                          }
                       }
                       String cardInquiry;
                       if(player1MaximumCardIndex!=-1)
                       {
                          cardInquiry = Card.getRankText(player1MaximumCardIndex);
                       }
                       else
                       {
                          cardInquiry = Card.getRankText(player2MinimumCardIndex);
                          player2CardTracker[player2MinimumCardIndex]++;
                       }
                       JOptionPane.showMessageDialog(null,"Player 2 is fishing for "+cardInquiry+(cardInquiry.equals("Six")?"e":"")+"s.");
                       CHECKING:
                       {
                          for(int i = 0; i < player1Hand.cards.size(); i++)
                          {
                             if(player1Hand.cards.get(i).getRankText().equals(cardInquiry)){player1Hand.dealTo(player1Hand.cards.get(i),player2Hand,false);break CHECKING;}
                          }
                          deck.dealTo(player2Hand,false);
                          if(!player2Hand.cards.get(player2Hand.cards.size()-1).getRankText().equals(cardInquiry))
                          {
                             status.setStatus("Player 1's turn.");
                             inquire.setEnabled(true);
                             player1Hand.setStackRules(player1HandStackRules);
                             JOptionPane.showMessageDialog(null,"Player 1's turn.");
                             return;
                          }
                       }
                    }
                 }
              }
          //  }});
        }
     };
     src.dropPile = player1Hand;
     deckStackRules = deck.getStackRules()|Stack.STACK_ACTION;
     deck.setStackRules(Stack.INACCESSIBLE,src);
     setMainPile(deck);
     src = new StackRuleConstraints()
     {
        public void stackDropAction()
        {
           deck.getStackRuleConstraints().stackClickAction();
        }
     };
     player1Hand.setStackRules(0,src);
     src = new StackRuleConstraints()
     {
        @Override
        public void stackDropAction()
        {
           if(playStack1.cards.size()==2)
           {
              if(playStack1.cards.get(0).getRank()==playStack1.cards.get(1).getRank())
              {
                 addPair(true);
              }
              else
              {
                 playStack1.dealTo(player1Hand,true);
                 playStack1.dealTo(player1Hand,true);
              }
           }
        }
     };
     src.restrictedFrom.add(player1Hand);
     playStack1.setStackRules(Stack.STACK_ACTION|Stack.RESTRICTED_STACK,src);
     src = new StackRuleConstraints()
     {
        @Override
        public void stackDropAction()
        {
           if(playStack2.cards.size()==2)
           {
              if(playStack2.cards.get(0).getRank()==playStack2.cards.get(1).getRank())
              {
                 addPair(false);
              }
              else
              {
                 playStack2.dealTo(player2Hand,false);
                 playStack2.dealTo(player2Hand,false);
              }
           }
        }
     };
     src.restrictedFrom.add(player2Hand);
     playStack2.setStackRules(Stack.STACK_ACTION|Stack.RESTRICTED_STACK,src);
     player1SidePnl.add(player1PairLbl,BorderLayout.NORTH);
     player2SidePnl.add(player2PairLbl,BorderLayout.NORTH);
     player1SidePnl.add(player1CardPairs,BorderLayout.CENTER);
     player2SidePnl.add(player2CardPairs,BorderLayout.CENTER);
     ws.add(player2SidePnl,BorderLayout.WEST);
     gbc.weighty = 1;
     gbc.anchor = gbc.NORTH;
     gbc.insets = new Insets(0,0,10,0);
     gbc.gridy = 0;
     centerPnl.add(player2Hand,gbc);
     gbc.anchor = gbc.CENTER;
     gbc.gridy = 1;
     centerPnl.add(playStack2,gbc);
     gbc.gridy = 2;
     centerPnl.add(deck,gbc);
     gbc.gridy = 3;
     centerPnl.add(playStack1,gbc);
     gbc.anchor = gbc.SOUTH;
     gbc.gridy = 4;
     centerPnl.add(player1Hand,gbc);
     ws.add(centerPnl,BorderLayout.CENTER);
     ws.add(player1SidePnl,BorderLayout.EAST);
     getContentPane().add(status,BorderLayout.SOUTH);
     status.add(inquire,BorderLayout.EAST);
     player1HandStackRules = player1Hand.getStackRules();
     setVisible(true);
     init();
  }

You can view the full code here: www.github.com/mfgravesjr Look in the repository named projects-in-progress.

Upvotes: 0

Views: 69

Answers (0)

Related Questions