Reputation: 315
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. I already made the JButton array a private one.
Here is the gui 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:
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. I hope someone can help me.
Upvotes: 0
Views: 218
Reputation: 285403
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. 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. To see that you are in fact doing this, your code (both classes) should call new GUI_Ingame()
only once. Myself, I'd give GUI_Ingame.java
a constructor where it creates its own JPanel and get rid of the start()
method. I'd also create the JFrame in the main method and add GUI_Ingame's JPanel to it, pack it, and set it visible.
And yes, avoid using null layouts. 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. 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.
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);
}
}
Upvotes: 2