Search code examples
javaswingjbuttongridbaglayout

Custom JButton not sizing properly?


I am creating a matching game using Netbeans, but not the GUI editor (it sucks). So, basically, I created a new class, called Card, that extends the JButton class. Upon construction, the button's size is set to 100px by 100px and an icon is set. When I add the button to a JPanel in a GridBagLayout, it is not the intended size.

Here is some of my code:

JFRAME CLASS:

package matchinggame;

... imports ...

public class MatchingGameWindow extends JFrame {

    Card[] cards = new Card[16]; //16 game cards

    public MatchingGameWindow() {
         ...
         //Create new game panel (for the cards)
         JPanel gamePanel = new JPanel(new GridBagLayout());
         //gamePanel.setSize(500,500); removed as it is not needed.
         ...
         this.add(gamePanel, BorderLayout.CENTER);
         //Create 16 card objects
         cards = createCards();

         //Create new grid bag constraints
         GridBagConstraints gbc = new GridBagConstraints();

         //Add the cards to the game panel
         int i=0;
         for (int y = 0; y < 4; y++) {
             gbc.gridy = y;
             for (int x = 0; x < 4; x++) {
                gbc.gridx = x;
                gamePanel.add(cards[i], gbc);
                i++;
             }
         }
    }

    public final Card[] createCards() {
        Card[] newCards = new Card[16];
        //New choices array
        ArrayList<Integer> choices = new ArrayList();
        int[] choiceValues = {0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7};
        //Add the initial choice values to the arraylist
        for (int i=0; i < choiceValues.length; i++) {
            choices.add(choiceValues[i]);
        }

        //Create 16 cards
        for (int i=0; i < 16; i++) {
            //Initial value of -1 for error checking
            int iconIndex = -1;
            //Loop until card is created
            while (iconIndex == -1) {    
                //Get a random number from 0 - 7
                Random r = new Random();
                int rInt = r.nextInt(8);
                //If the random number is one of the choices
                if (choices.contains(rInt)) {
                     //the icon # will be the random number
                     iconIndex = rInt;
                     //Get rid of that choice (it is used up)
                     choices.remove(new Integer(rInt));
                     //Create a new Card in the Card[]
                     newCards[i] = new Card(i,iconIndex);
                //If all the choices are gone
                } else if (choices.isEmpty()){
                    iconIndex = -1; //done creating this card (breaks out of loop)
                }
            }
        }
        //Return the created cards
        return newCards;
    }
}

CARD CLASS:

package matchinggame;

import javax.swing.ImageIcon;
import javax.swing.JButton;

public class Card extends JButton {

    final static ImageIcon defaultIcon = new ImageIcon("cardback.jpg");
    ImageIcon secretIcon;
    boolean isRevealed = false;

    ...

    public Card(final int cardIndex, int secretIconIndex) { 
        //Size is 100px by 100px            
        setSize(100, 100);
        //Default icon is card back image
        setIcon(defaultIcon);
        //Get the secret icon behind the back of the card
        secretIcon = icons[secretIconIndex];    
    }
}

And using this code I get a result of this: This is the result.

Any ideas as to what I am doing wrong here?

EDIT: I overrided the getPreferredSize method like Hovercraft Full Of Eels said, and it worked! I added this code in the Card class:

@Override
public Dimension getPreferredSize() {
    return new Dimension(100,100);
}

and got my desired result: Fixed!

Now I must be doing something wrong with the icons, as they are not showing up as they should.


Solution

  • You should not use setSize(...) in the class's constructor but rather override the class's getPreferredSize() method to return a Dimension(100, 100). And in fact you should have setSize(...) no-where in your program. Instead use decent layout managers, call pack() on the JFrame after adding all components and before setting it visible, and let the layout managers size the GUI appropriately.