Java Swing: Swing Worker, invokeAndWait and Overlapping JLabels

587 Views Asked by At

Hey guys I've come with 2 problems, both being Java Swing related. I am developing a card game in Java. I use arreays lists of type to hold the values of each card and I have a main Play() method that calls updates to the GUI using invokeLater and a Singleton approach to my GUI class.

  1. The first question is fairly simple. I create the cards on the GUI using JLabels like so; attaching relevent listeners and adding them to the appropriate panel, in this case, the 'Human Hand Panel':

     for (int i = 0; i < (HumanHand.size()); i++)
                {
                    Card card = HumanHand.get(i);
    
                    BufferedImage cardImage = null;
    
                    try {
    
                        cardImage = ImageIO.read(new File("card/" + card + ".jpg"));
                    } catch (IOException e) {
    
                        e.printStackTrace();
                    }
                    JLabel picLabel = new JLabel(new ImageIcon( cardImage ));
    
                    picLabel.addMouseListener((MouseListener) me);
                    HumanHandDisplay.add(picLabel);
    
                } 
                //HumanHandDisplay.validate();
                HumanHandDisplay.updateUI();
    

The problem I'm having is that when the human hand is more than 7 cards or so, it creates a larger panel area and starts a new row of cards beneath. What I would like to do is, when the hand reaches a certain size, the cards start to overlap eachother (like you would hold cards in your hand). I've messed about with .validate() but gotten nowhere. Any help you can give here would be most welcome.

  1. My second question is about using a Swing Worker to return the Human player's card selection. I have read a little bit about Swing workers but I'm unsure as to the best way to implement one in my own game. At present, using the console I have a scanner than takes the input of an int as the choice (the place of the specific card in the ArrayList). I would like this int to be selected by clicking on the card in the players hand. At the moment I use:

                 String name = "" + i;
                picLabel.setName(name);
    

    to set the names of the Card JLabels to the int in the for loop creating them (as shown^^), and I use:

     public void mouseClicked(MouseEvent e) {
        String name = ((JLabel)e.getSource()).getName();
        System.out.println("Working " + name);
        selection = Integer.parseInt(name);         
    }
    

    To return that int when one of the cards is clicked. Here is what I've been using to call the GUI methods from Play() aswell:

            SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                GUI.getInstance().UpdateHand();
    
            }
        }); 
    

    My question is, how can I get the Play method to call a method in the GUI class, which sets up the hand with the appropriate listeners (lets call it GUIPlayerSelection() for now) then wait for the player to click a card, which then returns the int to my Play() method in my main class that represents the card selected. I'm unsure as how to use invoke and wait, as in, if I use invoke and wait, will it just wait for the cards to be set up, or will it wait for the mouseClicked() method to finish aswell? Or will I have to do something else to make sure it waits for the mouse to be clicked after the hand set-up? And how then will I return that int? I've been told to use a swing worker but if someone could explain how I can implement that in this case that would be awesome.

Thank-you in advance.

1

There are 1 best solutions below

2
On

For your first question, are you having an issue getting the frame to repaint or with the layout of the cards?

If the latter, then you may want to have a look at Java Layout Managers, it describes how the content pane inside your JFrame organizes the components added to it.

If none of those will work for you (and I don't think they will with that you describe), you can use the setBounds method to manually align your JLabels.