简体   繁体   English

在JFrame构造函数之外添加JButton

[英]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. 我正在上课的纸牌游戏,需要DealButton分发一手纸牌并将其显示在框架中。 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. 我有一个遍历给定手的循环,可以正确地创建和显示卡,但是当该代码从构造函数移至DealButton的ActionListener时,将不显示任何内容。

Is there a way to add JButtons to the frame outside the constructor? 有没有一种方法可以将JButtons添加到构造函数外部的框架中?

Here is the code that should be displaying the hands: 这是应该显示指针的代码:

deck.shuffle(); 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. 检查是否确实需要在循环中添加hand1 (多次)-但这只是一个猜测而不知道它是什么。

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 仅应在事件调度线程(EDT)上更改Swing组件(JPanel,JButton等),在ActionListener中执行的代码就是这种情况
  • after layout related changes the validate method should be called to (re-)layout the component 与布局相关的更改后,应调用validate方法对组件进行(重新)布局

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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