I'm trying to make a simple calculator in Java using Swing, and I've created my buttons the following way:
//Our number keypad
public static JPanel numbers(){
//our panel to return
JPanel panel = new JPanel();
//Create and add 3x4 grid layout to panel
GridLayout gl = new GridLayout(3, 4);
panel.setLayout(gl);
//For creating and adding buttons to panel
for(int i = 0; i < 10; i++){
//Create a new button where the name is the value of i
String name = "" + i + "";
JButton button = new JButton(name);
//add action listener
button.addActionListener(handler);
//Add button to panel
panel.add(button);
}
return panel;
}
My question is how do I reference each specific button in my event handler? I can't think of a way to do this without having to manually create each button rather than using a loop.
Thanks.
In your listener, call event.getSource(), and that will return the button which has been pressed. Get the text of the button, and you have its number.
Or create a different instance of your handler for every button, and pass the value of the button (i) to the constructor of the handler. This last solution is cleaner, IMO, because it doesn't depend on the text of the button. If you replaced the text by an image, for example, the first technique wouldn't work anymore.
You can distinguish created buttons by adding the following inside handler:
String buttonText = ((JButton) e.getSource()).getText();
if (<text1>.equals(buttonText)){
//do the stuff
} else if (<text2>.equals(buttonText)){
//do the stuff
} else {
//do the stuff
}
Method #1: go through the child components of the parent JPanel (quite tedious, has to be rebuilt every time you modify the contents of that JPanel). Make sure they're JButtons by using an if . . instanceof clause.
Method #2: as you create them in that loop, add them to a List (or even better, a Map). I prefer a Map personally as it lets me customise the key for that specific JComponent
i.e.
HashMap<String, JComponent> buttonList = new HashMap<String, JComponent>();
for(. .) {
buttonList.put("nameForEachButton", button);
}
I recommend generating the button name based off of the loop counter. Either use your existing name value, or just set it to "button" + i;
Declare your buttons using an array.
JButton[] button = new JButton[9]; //outside the for loop
for (int i = 0; i < 10; i++) {
//put your code
button[i] = new JButton(name);
//your code
}
Related
I would like to create a minesweeper game. Firstly, this will work on buttons. I think I will work on two dimensional array, and there will be like boolean array that will present where are bombs, for example if booleanArray[0][4] is true, there is a bomb.
Now, how can I implement this in my buttons? I can set Names on these buttons, and then if I click some button, then I will get the name from this div. For example when i click first button, i will get "00" name, then i will get first letter "0" and second letter "0" and parse it to int. And this will be the indexes from my previous booleanArray, in this case it will be booleanArray[0][0].
So, can I do this another, better way, instead of that?
This is the way I will be creating the buttons:
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
JButton button = new JButton("");
button.setPreferredSize(new Dimension(50, 50));
button.setName(Integer.toString(i) + Integer.toString(j));
}
}
EDIT
I will have a two dimensional Array, that will reflect my buttons:
and now, how can I check if I hit the bomb after I click for example in the first button?
Just hold a two dimensional array of buttons,
JButton[][] myButtons = new JButton[10][10];
which you use to draw them and they all call the same method with their value
for (int x=0; x<10; x++){
for (int y=0; y<10; y++){
myButtons[x][y] = new JButton("0");
//add to page, or do it elsewhere
myButtons[x][y].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
selectionButtonPressed(x,y);
}
});
}
}
Then a call to yout method selectionButtonPressed() will tell you what button has been pressed, you can take action and even make changes to the button with myButtons[x][y].whatever()
That is one way but you should create the String of the name by using something like:
button.setName(i + ":" j);
This will make it easier to parse out the two values as you can just use the String.split(...) method.
Another option might be to create a HashTable with the JButton as the key and then use a Point object (representing the row/column) as the value Object of the HashTable. Then you just use the get(...) method of the HashMap to retrieve the Point for the clicked button.
Another option is to extend JButton and add two parameters (row, column) when creating the button. Then you also add getRow() and getColumn() methods.
Either of this approaches will keep the logic simple and you only need to create a single ActionListener to be used by all the buttons.
i have a multiple jradiobutton that is inside a for loop and i am trying to put listener on it and this is what i found:
Action listener for multiple radio buttons
Create two dimensional JRadioButton array like
JRadioButton[][] jRadioButtons = new JRadioButton[8][];
ButtonGroup bg = new ButtonGroup();
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(8, 8));
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
JRadioButton btn = new JRadioButton();
btn.addActionListener(listener);
btn.setName("Btn[" + i + "," + j + "]");
bg.add(btn);
panel.add(btn);
// can be used for other operations
jRadioButtons[i][j] = btn;
}
}
Here is single ActionListener for all JRadioButtons
ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JRadioButton btn = (JRadioButton) e.getSource();
System.out.println("Selected Button = " + btn.getName());
}
};
i kinda understand it but i still have few clarifications:
what's the purpose of two dimensional jradiobutton? i mean i kinda see that it is to set a name for the jradiobuttons but as far as my understanding goes, it's only for display. yes to confirm that that is the jradiobutton you've selected but i don't get what's the purpose of it in putting actionlistener
is the two dimensional jradiobutton really that necessary?
can i just use the name of jradiobuttons
to do something like this:
if(NameOfJRadioButton.isSelected())
{
//some procedures
}
^(i can't seem to convert that into code :/)
if so, how can i do it? or do you have any other suggestions on how to put listener for multiple jradiobuttons? thank you for any of your suggestions :)
On your first and second point, the reason for the two dimensional array is unknown as it is not your code, but is not necessary at all for the use of JRadioButtons. However it is useful to have all your buttons in some type of array, whether it be an arraylist, or a buttonGroup (swing list for buttons) for checking things with the buttons when an action is called. e.g. on your 3rd point, this array list would allow you to iterate through and check which buttons have been selected and act accordingly.
The purpose for the action listener is for executing an action when the user clicks on a button. The most general use for this is making it so the user is only allowed to select a certain amount of JRadioButtons or to disable them once they have been selected. e.g. at a character selection menu.
I'm a beginner in GUI.
Is there a quick way of setting the same JButton/Image to multiple locations within the GUI? For better clarification, if I want to use this JButton 10 times at different locations in my GUI, would I have to create a new JButton(new ImageIcon...) 10 times?
The buttons don't have to lead to anything, this is just for show.
JButton jb = new JButton(new ImageIcon("myImage.png"));
jb.setLocation(10,10);
jb.setSize(40, 40);
getContentPane().add(jb);
The short answer is, yes, you will need multiple instances of JButton.
You can use an Action which can be applied to multiple instance of a button (the same instance of Action). The Action class carries properties which will be used to configure the buttons, such as text and icon properties.
A component (like JButton) can only reside within in a single container, therefore, you will need multiple instances of JButton.
Take a look at How to Use Actions and How to Use Buttons, Check Boxes, and Radio Buttons for more details...
Generally, you should avoid using setLocation and setSize and rely more on the use of layout managers, but you've not provided enough context to say if this useful to you or not.
Yes, you need to create a Jbutton object for each desired instance.
Since you have so many JButton that are all similar, I suggest that you declare an array JButton[] buttons = new JButton[10]; and use a for loop to create each individual button and set their attributes.
If it is just for a show, I would do the following to show the 10 button in a row:
int buttonHeight = 10;
int buttonWidth = 10;
for (int i = 0; i < 10; i++) {
JButton button = new Button("Button " + i);
button.setSize(buttonWidth, buttonHeight);
button.setLocation(10 + i * buttonWidth, 10);
getContentPane().add(button);
}
import java.util.Scanner;
import javax.swing.*;
import java.awt.*;
class PROB4_CHAL1 extends JFrame
{
JButton b[]=new JButton[10];
public PROB4_CHAL1()
{
setLayout(null);
setVisible(true);
setSize(100,100);
for(int i=0;i<10;i++)
{
b[i]=new JButton(""+i);// or b[i]=new JButton(new ImageIcon("path"));
b[i].setBounds(i*10,i*20,50,20);
add(b[i]);
}
}
public static void main(String[] args)
{
new PROB4_CHAL1();
}
}
You can Create array of 'JButton [10]' .
I have 25 jButtons and i want to change their texts from a loop. Here is my code for 1 button..
void changeText(){
jButton1.setText(jButton1.getText().toUpperCase());
}
I want to do the same for all other buttons without writing a method for each.
Is it possible to use something like this?
void changeText(){
for(int i=0;i<25;i++){
String x = "jButton"+i;
x.setText(x.getText().toUpperCase());
}
}
Surely this wont work. Please suggest me a method.
You can do this by adding the buttons to a collection.
Something like this:
// initialization of jbuttons:
List<JButton> buttons = new ArrayList<JButton>();
JButton jbutton1 = new JButton();
// .. set properties
buttons.add(jbutton1);
// add more jbuttons to the list
Later you can iterate over the list of buttons:
for (JButton button : buttons) {
button.setText(button.getText().toUpperCase());
}
I have an array I fill with buttons and I want an individual button to change its text when clicked.
for (int i = 0; i<4; i++)
{
button[i] = new JButton ("Add");
button[i].addActionListener(this);
box[i] = new JComboBox();
foodOptions.add(box[i]);
foodOptions.add(button[i]);
}
public void actionPerformed (ActionEvent e)
{
button[this].setText("I've been clicked!");
}
The current doesn't work because of incompatible types, what format is appropriate?
Yes, it makes no sense to pass an object, this, into an array index which expects an int, not your GUI object, so I'm not sure what you were trying to achieve with this.
Just get a reference to the JButton that's been clicked from the ActionEvent's getSource() method:
JButton btn = (JButton)e.getSource();
btn.setText("I've been clicked");
Edit:
Also you should avoid using this as your ActionListener since this means that you're likely having your GUI class implement an ActionListener which is asking the poor class to be too many things, to do too much. You're much better off either using anonymous inner classes or else even better use AbstractActions.