I have a selectpic() method to set images in the jbuttons.
public void selectpic() {
rule rule = new rule();
rule.shuffle();
for (int i = 0; i < 9; i++) {
if (rule.pic[i] == 0) {
Icon0.setImage(Icon0.getImage().getScaledInstance(WIDTH,HEIGHT,Image.SCALE_DEFAULT));
panel1.add(new JButton(Icon0));
} else if (rule.pic[i] == 1) {
Icon1.setImage(Icon1.getImage().getScaledInstance(WIDTH,HEIGHT,Image.SCALE_DEFAULT));
panel1.add(new JButton(Icon1));
} else if (rule.pic[i] == 2) {
Icon2.setImage(Icon2.getImage().getScaledInstance(WIDTH,HEIGHT,Image.SCALE_DEFAULT));
panel1.add(new JButton(Icon2));
} else if (rule.pic[i] == 3) {
Icon3.setImage(Icon3.getImage().getScaledInstance(WIDTH,HEIGHT,Image.SCALE_DEFAULT));
panel1.add(new JButton(Icon3));
} else if (rule.pic[i] == 4) {
Icon4.setImage(Icon4.getImage().getScaledInstance(WIDTH,HEIGHT,Image.SCALE_DEFAULT));
panel1.add(new JButton(Icon4));
} else if (rule.pic[i] == 5) {
Icon5.setImage(Icon5.getImage().getScaledInstance(WIDTH,HEIGHT,Image.SCALE_DEFAULT));
panel1.add(new JButton(Icon5));
}
}
}
When each round is finished i have to call the selectpic() method again to change images.
However, i can't just simply call that method again to do it.
Q1. Is it necessary to remove the images first and then call the selectpic() again, so that it can change the images?
Q2. If so, i searched in forum and found using
xxxx.setImage(null);
can remove the image(xxxx is the name of that jbutton),
but in the selectpic(), i use this to add the jbuttons.
panel1.add(new JButton(Icon0));
how can i know the name of the jbuttons so that i can use xxxx.setImage(null); to remove the images first?
Thanks!!
You're not keeping track of your JButtons, and calling selectpic() fills the JPanel with buttons, so calling it multiple times will create a lot of buttons.
I recommend you to have your JButtons in the class fields, like this:
private JButton button1;
Then, when you initialize your UI, initialize your buttons too:
// UI init here
button1 = new JButton();
panel1.add(button1);
And in the selectpic method, set your icons.
button1.setIcon(choosedIcon);
PD: Now I look more carefully to your code, an array of JButtons would be better, I think. So, the field declaration would be this:
private JButton[] buttons = new JButton[numberOfButtons];
The initalization would be something like this:
for (int i = 0; i < numberOfButtons; i++) {
buttons[i] = new JButton();
panel1.add(buttons[i]);
}
And for setting the icon,
buttons[i].setIcon(chosedIcon);
PD2: I recommend you to start your variable names with a lowercase letter, like in the Naming Convention.
Related
I am trying to make a game in java where if you click on a button once it turns red, and if you click on it twice it turns blue, but I'm running into an issue where when I click one square once and it becomes red, if I click another once it turns blue, when I want the effect isolated to each square at a time(e.g. if I click one square once its red, click another twice its blue, and another square once its red). I also want it to reset after 3 clicks.
Here is my actions listener so far
JFrame frame = new JFrame(); //creates frame
JButton[][] grid; //names the grid of buttons
int clicked = 0;
public ButtonGrid(int width, int length) { //constructor
frame.setLayout(new GridLayout(width, length)); //set layout
grid = new JButton[width][length]; //allocate the size of grid
for(int y = 0; y < length; y++) {
for(int x = 0; x < width; x++) {
grid[x][y] = new JButton(); //creates a button
grid[x][y].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(clicked == 0) {
((JButton)e.getSource()).setBackground(Color.red);
clicked++;
} else if(clicked == 1) {
((JButton)e.getSource()).setBackground(Color.blue);
clicked++;
}
}
});
frame.add(grid[x][y]); //adds new button to grid
}
}
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack(); //sets appropriate size for frame
frame.setVisible(true); //makes frame visible
// ...
}
In your current implementation, clicked is a instance field of the parent class, which all your buttons/ActionListeners are using.
Instead, you need to isolate the property so that it can be better associated with a single button.
Now, you could create a custom class which extends from JButton, but IMHO, that's a little heavy handed and locks you into a single use case. Personally, I'd look towards implementating a concrete implementation of the ActionListener to provide this side effect.
For example...
public class CounterActionListener implements ActionListener {
private int counter;
#Override
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source instanceof JButton) {
JButton button = (JButton)source;
clicked++;
if(clicked == 0) {
button.setBackground(Color.red);
} else if(clicked == 1){
button.setBackground(Color.blue);
}
}
}
}
Then in your code, you just apply the listener to the button, for example...
grid[x][y] = new JButton(new CounterActionListener());
You could also follow this by making use of a "delegate", which actually performed the required operations, based on the number of clicks, which could be held in a model, but that's beyond the scope of the question ;)
You have one global clicked for all of them. Because of that actions are not isolated.
int clicked = 0;
Shouldnt be in class.
Your problem is that clicked is attached to the frame, not to the button. That means that there is only a single value of clicked for your entire application.
The easiest thing to do here would be to write a new class GregoryWeigelButton (or whatever) which extends JButton and has a int clicked=0 inside it (and probably a getter and setter). Then just check what the clicked value for that particular button is.
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.
Simplified: How to make String value to call specific existed JButton variable name in java?
I'm trying to make a non-ordinary Tic-Tac-Toe game...
Anyway, what I will post here is not really the whole concept of that. I just want to make it simple: I have 9 square jButtons named (3 by 3) (and maybe allow user to make 4x4, 5x5, 10x10 etc. via settings in future):
[markbox_00_00] / [markbox_00_01] / [markbox_00_02]
[markbox_01_00] / [markbox_01_01] / [markbox_01_02]
[markbox_02_00] / [markbox_02_01] / [markbox_02_02]
[btnSave] / [btnUndoActions]
where the first two digit represent the row and the next two is the column; and a save button (btnSave) and undo button(btnUndoActions).
Each markbox have default spring value of "0", when I click it turns "1"; and when I click "1" it turns "0". When you press undo button it will reset to last save.
Here is some of my simplified line of codes:
private byte markboxColLimit = 3, markboxRowLimit = 3, row, col;
private byte[][] saveNumber = new byte[markboxRowLimit][markboxColLimit];
private String buttonName;
public Astral_TicTacToe() {
initComponents();
/* I want something like this, but using a for loop based on markboxColLimit and
markboxRowLimit as limits */
markbox_00_00.setText("0");
markbox_00_01.setText("0");
markbox_00_02.setText("0");
markbox_01_00.setText("0");
markbox_01_01.setText("0");
markbox_01_02.setText("0");
markbox_02_00.setText("0");
markbox_02_01.setText("0");
markbox_02_02.setText("0");
/* I know the line below is wrong... what I'm trying is to avoid
* repetitiveness by looping and dynamically calling the variable
* name of JButtons, or in other ways...
*/
/* Attempting to make an alternative code from above (trying to make a loop instead) */
for(row = 0; row < markboxRowLimit; row++){
for(col = 0; col < markboxColLimit; col++){
buttonName = "markbox_0" + Byte.toString(row) + "_0" + Byte.toString(col);
buttonName.setText("0");
}
}
}
private void btnUndoActionsActionPerformed(java.awt.event.ActionEvent evt) {
markbox_00_00.setText(Byte.toString(saveNumber[0][0]));
markbox_00_01.setText(Byte.toString(saveNumber[0][1]));
markbox_00_02.setText(Byte.toString(saveNumber[0][2]));
markbox_01_00.setText(Byte.toString(saveNumber[1][0]));
markbox_01_01.setText(Byte.toString(saveNumber[1][1]));
markbox_01_02.setText(Byte.toString(saveNumber[1][2]));
markbox_02_00.setText(Byte.toString(saveNumber[2][0]));
markbox_02_01.setText(Byte.toString(saveNumber[2][1]));
markbox_02_02.setText(Byte.toString(saveNumber[2][2]));
}
private void btnSaveActionPerformed(java.awt.event.ActionEvent evt) {
saveNumber[0][0] = Byte.parseByte(markbox_00_00.getText());
saveNumber[0][1] = Byte.parseByte(markbox_00_01.getText());
saveNumber[0][2] = Byte.parseByte(markbox_00_02.getText());
saveNumber[1][0] = Byte.parseByte(markbox_01_00.getText());
saveNumber[1][1] = Byte.parseByte(markbox_01_01.getText());
saveNumber[1][2] = Byte.parseByte(markbox_01_00.getText());
saveNumber[2][0] = Byte.parseByte(markbox_02_00.getText());
saveNumber[2][1] = Byte.parseByte(markbox_02_01.getText());
saveNumber[2][2] = Byte.parseByte(markbox_02_02.getText());
}
private void markbox_00_00ActionPerformed(java.awt.event.ActionEvent evt) {
if("0".equals(markbox_00_00.getText()))
markbox_00_00.setText("1");
else
markbox_00_00.setText("0");
}
private void markbox_00_01ActionPerformed(java.awt.event.ActionEvent evt) {
if("0".equals(markbox_00_01.getText()))
markbox_00_00.setText("1");
else
markbox_00_00.setText("0");
}
....
private void markbox_02_02ActionPerformed(java.awt.event.ActionEvent evt) {
if("0".equals(markbox_00_00.getText()))
markbox_02_02.setText("1");
else
markbox_02_02.setText("0");
}
In short: how can I make String a specific variable name of JButton for calling/accessing/editing for their properties?
Example:
buttonName = markbox_01_02;
buttonName.setText("2");
is equavalent to markbox_01_02.getText("2");
I really appreciate the help, thank you...
P.S. I use to make JFrame in NetBeans Design (just click and drag the objects in palette window like JPanel, JButton, etc., so I don't type the code manually except making my own logical Method).
You probably need to redo your program and rephrase your question because it's kind of unclear where you're stuck that's why I wrote this answer as a Community Wiki.
The following program creates a GridLayout for the board and add 2 JButtons below it which contain "Save" and "Undo" buttons.
Whenever you press a button it will change it's text to 0 or 1 depending on the previous state of the button, and "Undo" button will undo last clic the same way, if it was 0 it will become 1 and viceversa.
I guess you should read How to write an ActionListener before copy-pasting this example, understand what it says and try to understand how this program works.
The logic to "Save" button is up to you 'cause I'm not sure what you wanna do there and I'm not gonna write all the code for you. This is made only for you to get an idea on how to handle events.
Also, the logic to end the game is left to you for the same reasons as the "Save" button.
I wish I knew how to record my screen in Ubuntu and save as GIF but here's a screenshot on how this program looks like:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class TicTacToe implements ActionListener {
JFrame frame;
JButton buttons[];
JPanel pane, buttonPane;
boolean pressed[];
JButton save, undo;
int n = -1;
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < buttons.length; i++) {
if(e.getSource() == buttons[i]) {
pressed[i] = !pressed[i];
buttons[i].setText(pressed[i] ? "1" : "0");
n = i;
break;
}
}
}
public TicTacToe () {
frame = new JFrame("Tic Tac Toe Game");
buttons = new JButton[9];
pane = new JPanel(new GridLayout(3, 3));
pressed = new boolean[9];
buttonPane = new JPanel(new FlowLayout());
save = new JButton("Save");
undo = new JButton("Undo");
for (int i = 0; i < buttons.length; i++) {
buttons[i] = new JButton("0");
pressed[i] = false;
}
for (JButton b : buttons) {
b.addActionListener(this);
pane.add(b);
}
undo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (n == -1) {
return;
}
pressed[n] = !pressed[n];
buttons[n].setText(pressed[n] ? "1" : "0");
}
});
buttonPane.add(save);
buttonPane.add(undo);
frame.add(pane, BorderLayout.PAGE_START);
frame.add(buttonPane, BorderLayout.CENTER);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main (String args[]) {
new TicTacToe();
}
}
JButton lunarButton = new JButton(new ImageIcon("assets/Buttons/moon.png"));
lunarButton.setActionCommand("switch");
c.gridwidth=1;
c.gridy = 0;
searchArea.add(lunarButton, c);
.
public void actionPerformed(ActionEvent ev)
{
int count = 1;
String action = ev.getActionCommand();
if("switch".equals(action))
{
ImageIcon sun = new ImageIcon("assets/sun.png");
ImageIcon moon = new ImageIcon("assets/moon.png");
changeLunar();
count++;
if (count % 2 == 0)
{
lunarButton.setIcon(sun);
}
else
{
lunarButton.setIcon(moon);
}
I have this code implemented, but eclipse tells me "lunarButton cannot be resolved", is it not able to see the lunarButton variable in my init() method? what am I missing here?
Your lunarButton may be declared locally, perhaps in the init method.
One solution: declare it as an instance field in the class, not in the init method.
Solution two: don't even worry about the variable. Get the JButton object from the ActionEvent parameter's getSource() method. Cast the object returned to JButton, and call whatever methods you'd like on it.
For example:
if("switch".equals(action))
{
// ImageIcon sun = new ImageIcon("assets/sun.png");
// ImageIcon moon = new ImageIcon("assets/moon.png");
JButton btn = (JButton) ae.getSource();
changeLunar();
count++;
if (count % 2 == 0)
{
btn.setIcon(sun);
}
else
{
btn.setIcon(moon);
}
As an aside: you really don't want to re-load the images from disk each time the button is pushed. Instead read the images in once, perhaps in a constructor, stuff them into an ImageIcon field, and use that field when needed.
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
}