简体   繁体   English

为什么我不能更改 JButton 的 Label?

[英]Why can't I change the Label of my JButton?

I am trying to change the Text in the JButton after the program started, because I get the information of what is supposed to be in there later.我试图在程序启动后更改 JButton 中的文本,因为我得到了稍后应该在其中的信息。 I already made the JButton array a private one.我已经将 JButton 数组设为私有数组。

Here is the gui class:这是图形用户界面 class:

import java.awt.EventQueue;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class GUI_Ingame {

    private JFrame frame;
    private JButton cards[][] = new JButton[4][8];

    /**
     * Launch the application.
     */
    public void start() {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    GUI_Ingame window = new GUI_Ingame();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public GUI_Ingame() {
        initialize();
    }
    
    public void setButtonText(int x, int y, String s) {
        cards[x][y].setText(s);

    }

    /**
     * Initialize the contents of the frame.
     */
    public void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 1920, 1080);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(null);
        int x = 80-140;
        for(int i = 0; i < 4; i++) {
            x += 140;
            int y = 0;
            for(int j = 0; j < 8; j++) {
                cards[i][j] = new JButton("");
                if(j == 0) {
                    y = 120;
                }else {
                    y += 120;
                }
                cards[i][j].setBounds(y, x, 100, 130);
                frame.getContentPane().add(cards[i][j]);

            }
        }



    }
}

Ant this is the part of the code to change the label: Ant 这是更改 label 的代码部分:

public class GameMaster {

    public static void main(String[] args) {

        GUI_Ingame in = new GUI_Ingame();
        in.start();

        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 8; j++) {

                Card c = f.getCardByPos(i, j);
                String s = "w";
                System.out.println(s);
                in.setButtonText(i, j, s);
            }

        }

    }

}

When I put a cards[i][j].setText("test") in the for loop where the JButtons are created it works just fine.当我将 cards[i][j].setText("test") 放在创建 JButtons 的 for 循环中时,它工作得很好。 I hope someone can help me.我希望有一个人可以帮助我。

You're creating two GUI_Ingame instances, one that you display (and never change the button state on), and the other you change the JButton text on.您正在创建两个 GUI_Ingame 实例,一个用于显示(并且从不更改按钮 state on),另一个用于更改 JButton 文本。 Create one and only one instance that is both displayed and that allows button text to be changed.创建一个且仅一个实例,既显示又允许更改按钮文本。

public class GameMaster {

    public static void main(String[] args) {

        // **** you create one instance here that is *never* shown: ****
        GUI_Ingame in = new GUI_Ingame();
        in.start();  // this call creates the 2nd instance

        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 8; j++) {

                Card c = f.getCardByPos(i, j);
                String s = "w";
                System.out.println(s);
                
                // and change the unshown instance buttons here
                in.setButtonText(i, j, s);
            }

        }

    }

}

and you create the other instance here which is displayed, but whose button texts are never changed:然后您在此处创建另一个显示的实例,但其按钮文本永远不会更改:

public void start() {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                
                // *** here you create and display the 2nd instance ***
                GUI_Ingame window = new GUI_Ingame();
                window.frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}   

Again, create one and only one instance and set the state of it.同样,只创建一个实例并设置它的 state。 To see that you are in fact doing this, your code (both classes) should call new GUI_Ingame() only once.要查看您是否确实在执行此操作,您的代码(两个类)应仅调用一次new GUI_Ingame() Myself, I'd give GUI_Ingame.java a constructor where it creates its own JPanel and get rid of the start() method.我自己,我会给GUI_Ingame.java一个构造函数,它在其中创建自己的 JPanel 并摆脱start()方法。 I'd also create the JFrame in the main method and add GUI_Ingame's JPanel to it, pack it, and set it visible.我还将在 main 方法中创建 JFrame 并将 GUI_Ingame 的 JPanel 添加到其中,将其打包并设置为可见。

And yes, avoid using null layouts.是的,避免使用 null 布局。 While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them.虽然 null 布局和setBounds()可能看起来 Swing 新手喜欢创建复杂 GUI 的最简单和最好的方法,但您创建的 Swing GUI 越多,您在使用它们时遇到的困难就越严重。 They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.它们不会在 GUI 调整大小时调整组件的大小,它们是增强或维护的皇家女巫,当放置在滚动窗格中时它们会完全失效,当在所有平台或与原始屏幕分辨率不同的屏幕分辨率上查看时它们看起来很糟糕.

For example:例如:

import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import javax.swing.*;

public class GameMaster2 {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {

            // **** create one and *only* one instance! ****
            GuiIngame2 gamePanel = new GuiIngame2();
            
            for (int row = 0; row < GuiIngame2.ROWS; row++) {
                for (int col = 0; col < GuiIngame2.COLS; col++) {
                    String text = String.format("[%d, %d]", col + 1, row + 1);

                    // *** set the button text of the buttons from that instance ***
                    gamePanel.setButtonText(row, col, text);
                    gamePanel.setButtonListener(row, col, e -> {
                        System.out.println("Button pressed: " + text);
                    });
                }
            }
            
            JFrame frame = new JFrame("GUI");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            // **** and display that same instance ****
            frame.add(gamePanel);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);         
        });
    }
}
@SuppressWarnings("serial")
class GuiIngame2 extends JPanel {
    public static final int ROWS = 4;
    public static final int COLS = 8;
    private static final int GAP = 6;
    private static final float SIZE = 40f;
    private JButton[][] cards = new JButton[ROWS][COLS];
    
    public GuiIngame2() {
        setLayout(new GridLayout(ROWS, COLS, GAP, GAP));
        int bGap = 2 * GAP;
        setBorder(BorderFactory.createEmptyBorder(bGap, bGap, bGap, bGap));
        
        for (int row = 0; row < cards.length; row++) {
            for (int col = 0; col < cards[row].length; col++) {
                cards[row][col] = new JButton("       ");
                cards[row][col].setFont(cards[row][col].getFont().deriveFont(Font.BOLD, SIZE));
                add(cards[row][col]);
            }
        }
    }
    
    public void setButtonText(int row, int column, String text) {
        cards[row][column].setText(text);
    }
    
    public void setButtonListener(int row, int col, ActionListener listener) {
        cards[row][col].addActionListener(listener);
    }
}

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

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