简体   繁体   中英

Adding JButtons Outside the JFrame Constructor

I am making a card game for class that requires a dealButton to deal out a hand of cards and display them in the frame. I have a loop that goes through the given hand and creates and displays the cards properly, but when that code is moved from the constructor and into the dealButton's ActionListener, nothing displays.

Is there a way to add JButtons to the frame outside the constructor?

Here is the code that should be displaying the hands:

deck.shuffle();

        Hand hands[] = deck.deal(4, 13);

        GridBagConstraints handCon1 = new GridBagConstraints();
        handCon1.insets = new Insets(0, 0, 0, 0);
        handCon1.gridy = 10;

        int handSize = hands[0].getCards().length;
        Card cards[] = hands[0].getCards();
        for(int i = 0 ; i < handSize ; i++){
           JButton card = new JButton();
           PlayCardListener playCard = new PlayCardListener(deck, cards[i], card);
           card.addActionListener(playCard);
           card.setIcon(new ImageIcon(cards[i].getImg()));
           card.setBorder(null);
           handCon1.gridx = i;
           add(hand1);
           hand1.add(card, handCon1);

It sure is possible:

public class Deal {

    public static void main(String[] args) {
        new Deal();
    }

    private JFrame frame;
    private JTextField statusField;
    private JButton dealButton;
    private JPanel buttonsPanel;

    private Deal() {
        statusField = new JTextField("starting - press DEAL");
        statusField.setEditable(false);

        dealButton = new JButton("DEAL");
        dealButton.addActionListener(this::doDeal);

        buttonsPanel = new JPanel();

        frame = new JFrame();
        frame.add(dealButton, BorderLayout.PAGE_START);
        frame.add(buttonsPanel, BorderLayout.CENTER);
        frame.add(statusField, BorderLayout.PAGE_END);
        frame.setSize(600, 200);
        frame.validate();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private void doDeal(ActionEvent ev) {
        buttonsPanel.removeAll();
        List<String> cards = Arrays.asList("A", "2", "3", "4", "5");
        Collections.shuffle(cards);
        for (String text : cards) {
            JButton button = new JButton(text);
            button.addActionListener(this::doCard);
            button.setActionCommand(text);
            buttonsPanel.add(button);
        }
        statusField.setText("new buttons");
        frame.validate();
    }

    private void doCard(ActionEvent ev) {
        String text = ev.getActionCommand();
        statusField.setText(text);  // just demo
    }
}

I suspect the following segment of your code:

for (...) {
    ...
   add(hand1);
   hand1.add(card, handCon1);

check if it is really needed to add hand1 in the loop (multiple times) - but just a guess without knowing what it is.

Some points to consider:

  • Swing components (JPanel, JButton, ...) should only be changed on the Event Dispatch Thread (EDT) - this is the case for code executed in the ActionListener
  • after layout related changes the validate method should be called to (re-)layout the component

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM