Creating an Array of JButton - java

Basically I am trying to make a Lightout game! I want to make an array of JButtons
so I can keep track of the index of each of them (the reason being the state of each button is dependant on the state of the others)
so far I have:
JPanel panel = new JPanel();
setTitle("Memory");
setContentPane(panel);
setPreferredSize(new Dimension(300, 300));
panel.setLayout(new GridLayout(5,5));
JButton[][] buttons = new JButton[5][5] ;
for (int i = 0; i < 5; i++)
for (int j = 0; j < 5; j++) {
buttons[i][j] = new JButton();
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setVisible(true);
}
But this isnt working how I expect it to. I just got a big blank JFrame when I run this. Any help would be appreciated

The attached code should fix it. You were creating button, but not adding it to the JFrame. I have edited the code to add action listener which accesses the id of the JButton and displays it , when you click it.
public class CodeSample extends JFrame {
private static final long serialVersionUID = -8134989438964195251L;
public CodeSample() {
JPanel panel = new JPanel();
setTitle("Memory");
setContentPane(panel);
setPreferredSize(new Dimension(300, 300));
panel.setLayout(new GridLayout(5, 5));
ButtonListener listener = new ButtonListener();
JButton[][] buttons = new JButton[5][5];
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
buttons[i][j] = new JButton();
buttons[i][j].setBackground(Color.black);
buttons[i][j].putClientProperty("id",
String.valueOf(i).concat(String.valueOf(j)));
buttons[i][j].addActionListener(listener);
panel.add(buttons[i][j]);
}
}
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setVisible(true);
}
public static class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(((JButton) e.getSource())
.getClientProperty("id"));
}
}
public static void main(String[] args) {
new CodeSample();
}
}

Related

How to detect which button was clicked - Java

Problem: below some code to make a frame filled with buttons. After the button is clicked, I would need to know the coordinates of the button clicked. The program will afterwards check the status of that specific tile and depending on the status it should change to a certain color. I'm having some issues when retracting this coordinate, could someone help me? (I'm only just learning how to program in Java, so my code might not be ideal)
Code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GUIBoard {
JPanel buttonPanel = new JPanel();
JButton button = new JButton();
JFrame frame;
ButtonClicked clicked = new ButtonClicked();
public GUIBoard(String title, int nbRows, int nbColumns) {
frame = new JFrame(title);
buttonPanel.setLayout(new GridLayout(nbRows, nbColumns));
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
for (int i = 0; i < nbRows; i++) {
for(int j = 0; j < nbColumns; j++) {
button = new JButton();
button.setBackground(Color.LIGHT_GRAY);
button.addActionListener(clicked);
gbc.gridx = j;
gbc.gridy = i;
buttonPanel.add(button, gbc);
}
}
frame.setPreferredSize(new Dimension(1000, 600));
frame.getContentPane().add(buttonPanel, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
private class ButtonClicked implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run(){
new GUIBoard("Batlleship Board", 10,10);
}
});
}
}
If by coordinates you mean the actualx and y placement location of the button clicked upon then you can use this within your buttons ActionPerformed event:
public void actionPerformed(ActionEvent e) {
JButton btn = (JButton)e.getSource();
System.out.println(btn.getX() + ", " + btn.getY());
}
Will print the top left location of the button clicked upon. This isn't very helpful however since these locations can change if the Form is resized in any way.
If you mean by grid location as in the row and column of the button clicked upon then the easiest would be to ensure that an identifier is applied to each of the buttons by placing the grid location into the buttons Name property, when creating your buttons, for example:
for (int i = 0; i < nbRows; i++) {
for (int j = 0; j < nbColumns; j++) {
button = new JButton();
// Apply an identifier to the Button:
button.setName(new StringBuilder("Button_").append(i)
.append(",").append(j).toString());
button.setBackground(Color.LIGHT_GRAY);
button.addActionListener(clicked);
gbc.gridx = j;
gbc.gridy = i;
buttonPanel.add(button, gbc);
}
}
Then in your buttons ActionPerformed event:
public void actionPerformed(ActionEvent e) {
JButton btn = (JButton)e.getSource();
System.out.println(btn.getName());
}
Now that I think I have understood what you want to do I am going to give you a new and easier approach:
Here is the code, you just need to use the method getSource() to get an instance of the button which has been pressed. Then you change the color.
public class GUIBoar {
JPanel buttonPanel = new JPanel();
JButton button = new JButton();
JFrame frame;
public GUIBoar(String title, int nbRows, int nbColumns) {
frame = new JFrame(title);
buttonPanel.setLayout(new GridLayout(nbRows, nbColumns));
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
for (int i = 0; i < nbRows; i++) {
for (int j = 0; j < nbColumns; j++) {
button = new JButton();
button.setBackground(Color.LIGHT_GRAY);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e){
Object source = e.getSource();
JButton b = (JButton)source;
b.setBackground(Color.RED); //IMAGINE THATS THE COLOR
}
});
gbc.gridx = j;
gbc.gridy = i;
buttonPanel.add(button, gbc);
}
}
frame.setPreferredSize(new Dimension(1000, 600));
frame.getContentPane().add(buttonPanel, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new GUIBoar("Batlleship Board", 10, 10);
}
});
}
}

Remove gap between GridLayout elements

I am trying to create a 9x9 grid of JTextFields using GridLayout, however I am unable to remove the gap between the JTextFields within the GridLayout.
I have tried setting the horizontal and vertical gap to 0 using setHgap and setVgap methods, but the gap still exists, where am I going wrong ?
This is what I have tried so far,
class BoardGUI extends JFrame implements ActionListener {
private JPanel centerPanel, bottomPanel;
private JTextField grid[][];
private JButton loadBtn, saveBtn, solveBtn;
private GridLayout gridLayout;
private final int N = 9;
private final int MAX_HEIGHT = 450;
private final int MAX_WIDTH = 500;
public BoardGUI() {
super("Solver v2.0");
centerPanel = new JPanel();
bottomPanel = new JPanel();
grid = new JTextField[N][N];
for(int i=0; i<N; i++)
for(int j=0; j<N; j++)
grid[i][j] = new JTextField(1);
loadBtn = new JButton("Load");
saveBtn = new JButton("Save");
solveBtn = new JButton("Solve");
gridLayout = new GridLayout(N,N);
gridLayout.setVgap(0);
gridLayout.setHgap(0);
initLayout();
registerEventListeners();
}
private void initLayout() {
centerPanel.setLayout(gridLayout);
for(int i=0; i<N; i++)
for(int j=0; j<N; j++)
centerPanel.add(grid[i][j]);
bottomPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
bottomPanel.add(loadBtn);
bottomPanel.add(saveBtn);
bottomPanel.add(solveBtn);
this.setLayout(new BorderLayout());
this.getContentPane().add(centerPanel, BorderLayout.CENTER);
this.getContentPane().add(bottomPanel, BorderLayout.SOUTH);
this.setSize(MAX_WIDTH, MAX_HEIGHT);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
private void registerEventListeners() {
loadBtn.addActionListener(this);
saveBtn.addActionListener(this);
solveBtn.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
}
}
Image:

JButton does not return the right text value

I have a problem regarding JButtons. I have a GridLayout of 20x20 JButtons. I want to get the value of a single button when I click on it. (x.getText()).
The sout prints the bottom right value only, no matter what button I click.
If I click the top left button it prints 19. The value I want to get back in this case is 0.
My code below.
public class MainFrame extends Frame implements MouseListener{
JButton button;
public MainFrame() {
setSize(new Dimension(1000, 1000));
addComponents();
}
private void addComponents(){
JPanel mainPanel = new JPanel(new BorderLayout());
JPanel top = new JPanel(new GridLayout(1,1));
JPanel center = new JPanel(new GridLayout(20, 20));
JLabel label = new JLabel("test");
top.add(label);
for (int i = 0; i < 20; i ++){
for (int j = 0; j < 20; j ++){
button = new JButton(String.valueOf(i));
button.addMouseListener(this);
center.add(button);
}
}
mainPanel.add(top, BorderLayout.NORTH);
mainPanel.add(center, BorderLayout.CENTER);
add(mainPanel);
}
#Override
public void mouseClicked(MouseEvent e) {
System.out.println(button.getText());
}
// Also implements multiple other methods from the interface, but irrelevant for my question.
New code (working code):
public class MainFrame extends Frame {
public MainFrame() {
setSize(new Dimension(1000, 1000));
addComponents();
}
private void addComponents(){
JPanel mainPanel = new JPanel(new BorderLayout());
JPanel top = new JPanel(new GridLayout(1,1));
JPanel center = new JPanel(new GridLayout(20, 20));
JLabel label = new JLabel("test");
top.add(label);
ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String text = e.getActionCommand();
System.out.println(text);
}
};
for (int i = 0; i < 20; i ++){
for (int j = 0; j < 20; j ++){
JButton button = new JButton(String.valueOf(i));
button.addActionListener(listener);
center.add(button);
}
}
mainPanel.add(top, BorderLayout.NORTH);
mainPanel.add(center, BorderLayout.CENTER);
add(mainPanel);
Don't use a MouseListener on a JButton since by doing this, your button will not respond to space bar presses if it has focus, and also if you disable the button, your MouseListener will still work, which is not correct behavior.
Instead use an ActionListener, a single one is all you need, one that is added to each and every button, and get the action command from the ActionEvent parameter.
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
String text = e.getActionCommand();
}
}
// add listener to all buttons in a for loop
Look at your code, you only have a single attribute button which value is printed in your mouseClicked method, so nothing surprising here.
Each button must have its own listener, so remove your attribute and use this code :
for (int i = 0; i < 20; i ++){
for (int j = 0; j < 20; j ++){
final JButton button = new JButton(String.valueOf(i));
button.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println(button.getText());
}
});
center.add(button);
}
}
You can also use an ActionListener instead of a MouseAdapter.
You have to declare an array of buttons then loop it to declare all buttons and to add action listener

problems adding arrays of jbutton and jlabel into arrays of jpanel unto a frame

i want to add 10 jlabel and 10 jbutton unto each jpanel. Now there are 10 jpanels which i want to add to a frame, so the jframe should show 100 jlabel, 100 jbutton with 10 jpanels.
My problem is that the frame only shows 10 jlabel and 10 jbutton. i dunno where am wrong.
here is my code
public class MultiPanel extends JFrame {
private JPanel[] panel;
private JLabel[] label;
private JButton[] button;
public MultiPanel() {
panel = new JPanel[10];
label = new JLabel[10];
button = new JButton[10];
for (int i = 0; i < label.length; i++) {
label[i] = new JLabel(String.valueOf(i + 1));
button[i] = new JButton("B");
label[i].setSize(50, 50);
panel[i] = new JPanel();
panel[i].setLayout(new FlowLayout(FlowLayout.CENTER));
panel[i].add(label[i]);
panel[i].add(button[i]);
add(panel[i]);
}
setLayout(new GridLayout(1, 10));
setSize(720, 560);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
MultiPanel m_pnl = new MultiPanel();
}
}
public class MultiPanel extends JFrame {
public MultiPanel() {
int increment = 0;
while(increment < 10){
JPanel toAdd = new JPanel();
for (int i = 0; i < 10; i++) {
JLabel l = new JLabel(String.valueOf(i + 1));
JButton b = new JButton("B");
l.setSize(50, 50);
toAdd.setLayout(new FlowLayout(FlowLayout.CENTER));
toAdd.add(l);
toAdd.add(b);
}
add(toAdd);
increment++;
}
setLayout(new GridLayout(1, 10));
setSize(720, 560);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
MultiPanel m_pnl = new MultiPanel();
}
}
Your logic was faulty... Try this. You have an outer whileloop that will create 10 JPanels like you want. The inner for loop adds 10 JLabels and JButtons to each JPanellike you want. Then you just add all ten JPanels to the main JPanel which is slapped on the JFrame. I have compiled and run this and it works
Before you were only adding one label and button to each panel. You had 10 panels each with 1 button and one label

Java add buttons dynamically as an array [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
java - How would I dynamically add swing component to gui on click?
I want to add array of buttons dynamically.
I tried like this:
this.pack();
Panel panel = new Panel();
panel.setLayout(new FlowLayout());
this.add(panel);
panel.setVisible(true);
for (int i = 0; i < Setting.length; i++) {
for (int j = 0; j < Setting.width; j++) {
JButton b = new JButton(i+"");
b.setSize(30, 30);
b.setLocation(i * 30, j * 30);
panel.add(b);
b.setVisible(true);
}
}
but didn't get anything , what mistake did I make?
Edit
I have jFrame class "choices" on it i have a button , when I press the button, this is supposed to happen:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
structure.Setting s = new Setting(8, 8, 3, 1, 1);
Game g = new Game();
g.setSetting(s);
this.dispose();
g.show();
}
then i go to the Game class (also jFrame class) to the function setSetting and it is like this:
void setSetting(Setting s) {
this.setting = s;
structure.Game game = new structure.Game(setting);
JPanel panel = new JPanel(new GridLayout(5, 5, 4, 4));
for (int i = 1; i <= 5; i++) {
for (int j = 1; j <= 5; j++) {
JButton b = new JButton(String.valueOf(i));
panel.add(b);
}
}
add(panel);
pack();
setVisible(true);
}
structure.Setting setting;
}
You may use GridLayout to add equal height/width buttons:
public class Game extends JFrame {
private JPanel panel;
public Game(int rows,int cols,int hgap,int vgap){
panel=new JPanel(new GridLayout(rows, cols, hgap, vgap));
for(int i=1;i<=rows;i++)
{
for(int j=1;j<=cols;j++)
{
JButton btn=new JButton(String.valueOf(i));
panel.add(btn);
}
}
add(panel);
pack();
setVisible(true);
}
}
and code in button's handler should be:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
Game g = new Game(5,5,3,3);
}
Note that you can also pass Setting object reference via Game constructor (when you may add widgets dynamically) instead of calling setSetting method.
The JPanel is already under the control of a layout manager, setting the size and position of the buttons is irrelevant, as they will changed once the panel is validated.
Try, instead, adding the panel AFTER you've populated it with buttons..
UPDATED with Example
Without further evidence, we are only guessing...You now have two people who have no issues.
Panel panel = new Panel();
for (int i = 0; i < Setting.length; i++) {
for (int j = 0; j < Setting.width; j++) {
jButton b = new jButton(i + "");
panel.add(b);
}
}
this.add(panel);
public class BadBoy {
public static void main(String[] args) {
new BadBoy();
}
public BadBoy() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
int buttonCount = (int) Math.round(Math.random() * 20);
int columnCount = (int) Math.round(Math.random() * 20);
JPanel buttonPane = new JPanel(new GridLayout(0, columnCount));
for (int i = 0; i < buttonCount; i++) {
JButton b = new JButton(i + "");
buttonPane.add(b);
}
frame.add(buttonPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ButtonPane extends JPanel {
public ButtonPane() {
}
}
}
I am guessing that this extens or is some kind of frame?
First step is to pack the frame by doing this.pack(); sets the frame size ti just fit all objects.
I assume you have set it to visible?
Now you should be able to see the buttons.
If you want a different layout use panel.setLayout(new SomeLayout);
Try to use setBounds(x,y,width,heigth) method
setBound method
for (int i = 0; i < 1; i++) {
for (int j = 0; j <1; j++) {
JButton b = new JButton("button");
b.setBounds(500, 500, 100, 20);
this.add(b);
}
}
this.repaint();
this.validate()

Categories