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);
}
});
}
}
Related
What I am after is I would like for whenever someone checks a checkbox, the text for which the box they selected is output to the right panel(I have a split pane). Right now it is not responding so I don't think my BoxHandler is working properly(implements ItemListener). My function addBoxListeners is supposed to add item listeners for each checkbox that I have and the function I overrode in BoxHandler, function itemStateChanged should add text to the right panel, and I know that addText is working because I tested it outside of the itemListener stuff.
void addText(String s) { // adds text to the right panel, adds string s
JLabel temp = new JLabel();
temp.setText(s);
temp.setBorder(border1);
rightPanel.add(temp);
}
void addBoxes() {
int i = 0;
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
for (i = 0; i < 10; i++) {
JCheckBox tempBox = new JCheckBox("word " + i);
boxes.add(tempBox);
leftPanel.add(tempBox, gbc);
//leftPanel.add(new JCheckBox("word" + i), gbc);
}
}
private class BoxHandler implements ItemListener{
public void itemStateChanged(ItemEvent event) {
for (JCheckBox checkBox : boxes) {
if (checkBox.isSelected() ) {
addText(checkBox.getText());
}
}
}
}
void addBoxListeners() { // add listeners to all the boxes in the arraylist
BoxHandler handler = new BoxHandler();
int i = 0;
for ( i = 0; i < boxes.size(); i++) {
boxes.get(i).addItemListener(handler);
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
CheckBox2 cb = new CheckBox2();
cb.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
cb.pack();
cb.setLocationRelativeTo(null);
cb.addBoxListeners();
cb.setVisible(true);
}
Below is part of my class declaration:
public class CheckBox2 extends JFrame {
private ArrayList<JCheckBox> boxes = new ArrayList<JCheckBox>();
JSplitPane splitPane;
EmptyBorder border1 = new EmptyBorder(5, 5, 5, 5);
private JPanel leftPanel = new JPanel();
private JPanel rightPanel = new JPanel();
JLabel labelOne = new JLabel();
JLabel labelTwo = new JLabel();
...
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();
}
}
If someone could review my code for me, give me some pointers etc, I would be very grateful!
So in this game in case you've never played Mastermind, basically three colours are hidden in a specific order and the user has to guess what they are out of four possible colours. The code appears to work fairly well, even though it is currently unfinished, however an odd glitch occurs once the user wins. When the player properly guesses the three hidden colours, they are prompted to press the "Play again" button, which is then supposed to reset the game, which it appears to do, however once the user inputs another colour into the JTextFields designated to do so, the words last entered in those fields are revealed. I have implemented a small line that displays the word "working" on a nearby JLabel to show that the doClick() methods are activating, but the reset button doesn't work as intended, even though the newGame button does. Its an odd glitch, if anyone has a fix or reason for this glitch or any other general improvements you would make my day!
import java.awt.Color;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Summative2 extends JFrame {
static int guessNum;
static String colourGuess[] = new String[3];
static String colourArgument;
static int[] solution = new int[3];
public Summative2() {
for (int x=0;x<3;x++)
{
solution[x] = solution(); //Setting the solution for the first game
}
displayIntro(); //Activating the intro screen to start the program
}
public void displayIntro()
{
JPanel introPanel = new JPanel(new GridBagLayout());
this.getContentPane().add(introPanel);
GridBagConstraints c = new GridBagConstraints(); //The variable name being defined for the layout's constraints
introPanel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); //Setting the orientation of the Grid layout
c.insets = new Insets(2,2,2,2); //Basic spacing and anchoring
c.anchor = GridBagConstraints.CENTER;
JLabel welcome = new JLabel("Welcome to MASTERMIND");
c.ipady = 40;
c.gridx = 1; //Large welcome label, introducing the game
c.gridy = 0;
c.gridwidth = 3;
introPanel.add(welcome, c);
c.ipady = 0; //Resetting the characteristics of the components back to normal after the large intro message
c.gridwidth = 1;
JButton start = new JButton ("Start");
c.gridx = 1; //The start button
c.gridy = 1;
introPanel.add(start, c);
JLabel space = new JLabel(" ");
c.gridx = 2;
c.ipadx = 10; //Space between the Start and Rules buttons
c.gridy = 1;
introPanel.add(space, c);
c.ipadx= 0;
JButton rulesButton = new JButton("Rules");
c.gridx = 3; //Rules button
c.gridy = 1;
introPanel.add(rulesButton, c);
rulesButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
introPanel.setVisible(false);
displayRules("intro"); //Makes the intro panel invisible and activates the rules panel, along with an argument that tells the displayRules method to return the user to the intro screen when they press back after reading the rules
}
});
start.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
introPanel.setVisible(false); //Makes the intro invisible and starts the main game.
displayGame(false);
}
});
}
public void displayRules(String previousScreen) {
JPanel rulesPanel = new JPanel(new GridBagLayout());
GridBagConstraints r = new GridBagConstraints();
rulesPanel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
this.getContentPane().add(rulesPanel);
JTextField rulesText = new JTextField("insert rules here");
rulesText.setEditable(false);
r.gridx = 0;
r.gridy = 0;
r.gridwidth = 3;
r.ipady=100; //Big rules text box` NOT YET FINISHED
r.ipadx = 100;
rulesPanel.add(rulesText, r);
r.gridwidth =1;
r.ipadx=1;
r.ipady=1;
JButton backFromRules = new JButton("Back");
r.gridx = 2; //back button
r.gridy=1;
rulesPanel.add(backFromRules, r);
backFromRules.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
rulesPanel.setVisible(false);
if (previousScreen.compareTo("intro")==0) //When the user presses the back button they are returned to the screen from which they activated the rules screen
{
displayIntro();
}
if (previousScreen.compareTo("game")==0)
displayGame(false);
}
});
}
public void displayGame(boolean restart)
{
JPanel gamePanel = new JPanel(new GridBagLayout());
GridBagConstraints g = new GridBagConstraints();
gamePanel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
this.getContentPane().add(gamePanel);
g.anchor=GridBagConstraints.WEST;
g.weightx =1;
int coloursY = 0;
JButton redButton = new JButton("Red");
redButton.setBackground(Color.RED); //the red button, which is red
g.gridx= 0;
g.gridy=coloursY;
gamePanel.add(redButton, g);
JButton greenButton = new JButton("Green");
greenButton.setBackground(Color.GREEN);
g.gridx = 1; //The green button, which is green
g.gridy = coloursY;
gamePanel.add(greenButton, g);
JButton blueButton = new JButton("Blue");
blueButton.setBackground(Color.CYAN); //The blue button, which is cyan
g.gridx =2;
g.gridy=coloursY;
gamePanel.add(blueButton, g);
JButton yellowButton = new JButton("Yellow");
yellowButton.setBackground(Color.yellow); //The yellow button which is yellow
g.gridx=3;
g.gridy=coloursY;
gamePanel.add(yellowButton, g);
g.weightx=0;
g.weighty=0;
JLabel firstGuess = new JLabel("First Block Guess:");//The label for the first guess in each guessing sequence, followed by labels for the seconds and third
g.gridx = 0;
g.gridy=1;
g.gridwidth = 2;
gamePanel.add(firstGuess, g);
JLabel secondGuess = new JLabel("Second Block Guess:");
g.gridx = 0;
g.gridy=2;
gamePanel.add(secondGuess, g);
JLabel thirdGuess = new JLabel("Third Block Guess:");
g.gridx = 0;
g.gridy=3;
gamePanel.add(thirdGuess, g);
JTextField guessOne = new JTextField(""); //The text field where the user can enter thier guess for the first colour in a possible solution
guessOne.setPreferredSize(new Dimension(50,24));
g.gridx = 2;
g.gridy = 1;
guessOne.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
gamePanel.add(guessOne, g);
JTextField guessTwo = new JTextField(""); //Second colour
guessTwo.setPreferredSize(new Dimension(50,24));
g.gridx = 2;
g.gridy = 2;
gamePanel.add(guessTwo, g);
JTextField guessThree = new JTextField(""); //Third
guessThree.setPreferredSize(new Dimension(50,24));
g.gridx = 2;
g.gridy = 3;
gamePanel.add(guessThree, g);
JButton update = new JButton();//The update button, which doesn't exist but I used it as a type of repeatable method for whenever the user presses a colour button
JLabel GOneIndicator = new JLabel("<--"); //These arrows move when the user presses a colour button, letting them know where their next colour guess will be applied
g.gridx = 3;
g.gridy = 1;
gamePanel.add(GOneIndicator, g);
JLabel GTwoIndicator = new JLabel("<--");
g.gridx = 3;
g.gridy = 2;
gamePanel.add(GTwoIndicator, g);
GTwoIndicator.setVisible(false);
JLabel GThreeIndicator = new JLabel("<--");
g.gridx = 3;
g.gridy = 3;
gamePanel.add(GThreeIndicator, g);
GThreeIndicator.setVisible(false);
g.gridwidth = 2;
g.fill = GridBagConstraints.HORIZONTAL;
JButton submitButton = new JButton("SUBMIT"); //Submit guess
g.gridx = 0;
g.gridy = 4;
gamePanel.add(submitButton, g);
JButton resetButton = new JButton("Reset"); //Reset your guess JTextFields
g.gridx = 2;
g.gridy = 4;
gamePanel.add(resetButton, g);
JButton newGame = new JButton("New Game"); //Generates a new solution and presses the reset button
g.gridx = 0;
g.gridy = 5;
gamePanel.add(newGame, g);
JButton rulesButton = new JButton("Rules");
g.gridx = 2; //Displays the rules
g.gridy = 5;
gamePanel.add(rulesButton, g);
submitButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String guess[] = new String[3];
boolean proper = true;
guess[0]= guessOne.getText();
guess[1] = guessTwo.getText();
guess[2] = guessThree.getText();
for (int y = 0;y<3;y++)
{
if ((guess[y].compareToIgnoreCase("blue")!=0) && (guess[y].compareToIgnoreCase("red")!=0) && (guess[y].compareToIgnoreCase("green")!=0) && (guess[y].compareToIgnoreCase("yellow")!=0))
{
proper = false; //If one of the text fields had a word that wasn't one of the colours available for guessing, the user will be told so.
}
}
if (proper)
check(guess);//If everything was in order, check the guess against the solution
else
errorWindow();//Otherwise, nope
}
});
resetButton.addActionListener(new ActionListener() {//Sets all of the textFields blank, the guessnumber to 1 and makes the fiirst arrow appear as if it were the first guess.
#Override
public void actionPerformed(ActionEvent e) {
guessOne.setText("");
guessTwo.setText("");
guessThree.setText("");
guessNum=1;
GOneIndicator.setVisible(true);
GTwoIndicator.setVisible(false);
GThreeIndicator.setVisible(false);
}
});
newGame.addActionListener(new ActionListener () {
#Override
public void actionPerformed(ActionEvent e) {//Clicks the reset and generates a new solution set.
resetButton.doClick();
for(int d=0;d<3;d++)
solution[d]= solution();
}
});
if (restart)//If this screen was generated from the user pressing the play again button after winning, the game should be automatically reset and new solutions generated, this is bugging out somehow.
{
newGame.doClick();
GOneIndicator.setText("working");
resetButton.doClick();
restart=false;
}
rulesButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {//more rules display that isnt finished yet
gamePanel.setVisible(false);
displayRules("game");
}
});
update.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {//When a colour button is pressed, the next guess Field is filled in order, depending on the last one that was filled
colourGuess[guessNum-1] = colourArgument;
if (guessNum ==1 ){
guessOne.setText(colourArgument);
GOneIndicator.setVisible(false);
GTwoIndicator.setVisible(true);
guessNum++;
}
else if (guessNum ==2){
guessTwo.setText(colourArgument);
GTwoIndicator.setVisible(false);
GThreeIndicator.setVisible(true);
guessNum++;
}
else if (guessNum==3){
guessThree.setText(colourArgument);
GThreeIndicator.setVisible(false);
GOneIndicator.setVisible(true);
guessNum = 1;
}
}
});
redButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) { //Red is put into the next guess slot0
colourArgument = "Red";
update.doClick();
}
});
blueButton.addActionListener(new ActionListener() {//Then blue
#Override
public void actionPerformed(ActionEvent arg0) {
colourArgument = "Blue";
update.doClick();
}
});
yellowButton.addActionListener(new ActionListener() {//Or yellow
#Override
public void actionPerformed(ActionEvent arg0) {
colourArgument = "Yellow";
update.doClick();
}
});
greenButton.addActionListener(new ActionListener() {//or green
#Override
public void actionPerformed(ActionEvent arg0) {
colourArgument = "Green";
update.doClick();
}
});
}
public void check(String guess[])
{
JFrame checkWindow = new JFrame();
checkWindow.setSize(300,100);
JPanel pane = new JPanel(new GridBagLayout());
checkWindow.getContentPane().add(pane); //This is all to set up the initial window generally, and activate the layouts and whatnot
GridBagConstraints c = new GridBagConstraints();
pane.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
checkWindow.setVisible(true);
c.insets = new Insets(2,2,2,2);
int numGuess[] = new int[3]; //
int colourCount=0;
int positionCount=0; //Converts the information in the textFields to numbers which can be more easily compared
for (int x =0;x<3;x++)
{
if (guess[x].compareToIgnoreCase("red")==0)
{
numGuess[x] = 1;
}
if (guess[x].compareToIgnoreCase("blue")==0)
{
numGuess[x] = 2;
}
if (guess[x].compareToIgnoreCase("green")==0)
{
numGuess[x] = 3;
}
if (guess[x].compareToIgnoreCase("yellow")==0)
{
numGuess[x] = 4;
}
}
for (int z=0;z<3;z++) //Runs through the inputs compared to the solution, finding out how many of the colours were correct, and any of those colours that were in the correct positions
{
boolean guessed = false;
for (int k=0;k<3;k++)
{
if (solution[z] == numGuess[k])
{
guessed = true;
}
}
if (solution[z] == numGuess[z])
positionCount++;
if (guessed)
colourCount++;
}
c.fill=GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.CENTER;
if (positionCount ==3) //If all three positions are correct the user wins
{
JLabel colours = new JLabel(guess[0] + ", " + guess[1] + ", " + guess[2] + " is correct!");
c.gridx=0;
c.gridy=0;
pane.add(colours, c);
JLabel winner = new JLabel("You WIN!");
c.gridx=0;
c.gridy=1;
pane.add(winner, c);
JButton playAgain = new JButton("Play Again");
c.gridx=0;
c.gridy=1;
pane.add(playAgain, c);
playAgain.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {//Glitch causing button
for(int x=0;x<3;x++)
{
solution[x] = (int) (Math.random()*4)+1;
}
checkWindow.dispose();
displayGame(true);
}
});
}
else
{
JLabel labelOne = new JLabel(guess[0] + ", " + guess[1] + ", " +guess[2]);//If the user doesn't win, how many correct colours and positions they had are displayed
c.gridx = 0;
c.gridy = 0;
pane.add(labelOne, c);
JLabel colourMessage = new JLabel("You had " + colourCount + " correct colours.");
c.gridx=0;
c.gridy=1;
pane.add(colourMessage, c);
JLabel positionMessage = new JLabel("You had " + positionCount + " in the correct positions");
c.gridx=0;
c.gridy=2;
pane.add(positionMessage, c);
}
}
public void errorWindow()
{
JFrame checkWindow = new JFrame();
checkWindow.setSize(200,100);
JPanel pane = new JPanel(new GridBagLayout());//This window is displayed if the user inputs impossible values for their colour guesses
checkWindow.getContentPane().add(pane);
GridBagConstraints c = new GridBagConstraints();
pane.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
checkWindow.setVisible(true);
JLabel whoops = new JLabel("Try Again with valid colours.");
c.gridx=0;
c.gridy=0;
pane.add(whoops, c);
}
public static void main(String[] args) {
Summative2 frame = new Summative2(); //main method making the JFrame work properly
guessNum = 1;
frame.pack();
frame.setVisible(true);
frame.setSize(300, 225);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static int solution()
{
return (int) (Math.random()*4+1);//Solution method returning random numbers between 1 and 4 for solutions.
}
}
Every time you call the check() method, you're creating new ActionListener and registering it on the playAgain button.
This way, you get lots and lots of action listeners, and once the user finally clicks the playAgain button, they are all called, one by one.
You can see that yourself by setting a breakpoint inside the ActionListener code and debugging the application.
The solution would be to move that logic out of the check() method, to someplace where the form is initialized.
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
for(gbc.gridy = 3; gbc.gridy > 0; gbc.gridy--)
for(gbc.gridx = 0; gbc.gridx < 3;gbc.gridx++)
{
grid[btnNum] = new JButton("" + (btnNum+1));
grid[btnNum].setPreferredSize(new Dimension(75,75));
frame.add(grid[btnNum], gbc);
grid[btnNum].addActionListener(this);
grid[btnNum].addKeyListener(this);
btnNum++;
}
I have an array of buttons displayed in a 3x3 grid and each one has an action listener.
public void actionPerformed(ActionEvent e){
String output = "";
if(e.getSource() == grid[0]){
System.out.println("button 1");
}
}
Is this not correct?
Complete example in context:
public class ButtonGrid implements ActionListener, KeyListener{
JFrame frame=new JFrame(); //creates frame
JButton[] grid; //names the grid of buttons
public ButtonGrid(){ //constructor
frame.setTitle("MPC");
frame.setLayout(new GridBagLayout()); //set layout
JButton[] grid=new JButton[12]; //allocate the size of grid
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
int btnNum = 0;
grid[9] = new JButton("0");
grid[9].setPreferredSize(new Dimension(75,75));
grid[10] = new JButton("-");
grid[10].setPreferredSize(new Dimension(75,75));
grid[11] = new JButton("=");
grid[11].setPreferredSize(new Dimension(75,75));
frame.add(grid[9], gbc);
gbc.gridx++;
frame.add(grid[10], gbc);
gbc.gridx++;
frame.add(grid[11], gbc);
for(gbc.gridy = 3; gbc.gridy > 0; gbc.gridy--)
for(gbc.gridx = 0; gbc.gridx < 3;gbc.gridx++){
grid[btnNum] = new JButton("" + (btnNum+1));
grid[btnNum].setPreferredSize(new Dimension(75,75));
frame.add(grid[btnNum], gbc);
grid[btnNum].addActionListener(this);
grid[btnNum].addKeyListener(this);
btnNum++;
}
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack(); //sets appropriate size for frame
frame.setVisible(true); //makes frame visible
}
public static void main(String[] args) {
new ButtonGrid();//makes new ButtonGrid with 2 parameters
}
public void actionPerformed(ActionEvent e){
String output = "";
if(e.getSource() == grid[0]){
System.out.println("button one");
//playSound(abc.kick);
}}
Your grid variable is null in the ActionListener. My bet -- you're shadowing the variable.
Solution: make sure that you initialize the grid field, not a local grid variable
public class ButtonGrid implements ActionListener, KeyListener{
JFrame frame=new JFrame();
JButton[] grid; // grid field remains null
public ButtonGrid(){
frame.setTitle("MPC");
frame.setLayout(new GridBagLayout());
JButton[] grid=new JButton[12]; // ****** a LOCAL variable ******
At the indicated line you create the shadowed variable. This means because you redeclare grid within the constructor, you initialize only the local variable and not the field that was declared in the class leaving the field null. Solution: Don't re-declare grid. Change it to:
public class ButtonGrid implements ActionListener, KeyListener{
JFrame frame = new JFrame();
JButton[] grid;
public ButtonGrid(){
frame.setTitle("MPC");
frame.setLayout(new GridBagLayout());
grid = new JButton[12]; // ***** this initializes the field ******
Try this.
public void actionPerformed(ActionEvent e){
String output = "";
for(int i=0; i<=grid.length; i++){
if(e.getSource() == grid[i]){
System.out.println("button "+i);
}
}
}