How to call a variable using another variable? - java

So I have 44 buttons in my program, and for one of my methods I want to re-enable all of them. the buttons are easily named btn1, btn2, btn3...btn44. Is there a way I can use a for loop to enable all of them?
I would love to do something like this but I cannot find the resources necessary.
for(int i == 0, i < 44, i++){
btn<i>.setEnabled(true);
}
Without that I would have to go through each button
btn1.setEnabled(true);
btn2.setEnabled(true);
...
btn44.setEnabled(true);
I know this alternate method isn't that bad but I have similar areas in my code where a technique like the one I am looking for would be very useful. Thank you!

You should make an array of buttons:
Button[] buttons = new Button[44];
for (int i = 0; i < 44; i++) {
// Do stuff with buttons[i]
}
You can't get the value of a variable using its string name representation because that would not compile very well; it is possible but not just using Java and it would require some weird roundabout way of doing it. Just use an array.

Create a list to store all the buttons and the iterate it.
...
List<Button> buttons = new ArrayList<>();
buttons.add(btn1);
buttons.add(btn2);
...
buttons.add(btn42);
And then use that list for mass actions:
void setStatus(boolean enabled) {
for (Button b : buttons ) {
b.setEnabled(enabled);
}
}

You could add you Buttons to a collection, like a List (if you have not done so already). Then it's easier to iterate over them.
// this list will grow automatically when you add new elements
List<Button> buttons = new ArrayList<>();
// when you create a button in your code, add them to your collection/list
buttons.add(new Button("1"));
buttons.add(new Button("2"));
buttons.add(new Button("3"));
buttons.add(new Button("4"));
buttons.add(new Button("5"));
// etc.
// in Java 8 you can use lambdas to update your buttons like this
buttons.forEach(button -> button.setEnabled(true));
Just make sure you are importing the correct version of List.
I.e make sure you use this list import java.util.List; and not the one in the windowing toolkit (i.e. not import java.awt.List;)

Related

How do I modify 100 objects without having to write 100 lines of code? (Java)

I have a lot of JButton objects which have the names a, b, c, d, ...
I want to set all of their states according to a boolean array I have. For example, if the boolean array is [true, false, true], I want to set a's state to true, b's state to false, and c's state to true. (using JButton.setEnabled(boolean))
The problem is that I have too many objects and if I have to change their states one by one, the code is going to get long and redundant.
How do I do this in a simple way?
I'm programming in Netbeans, Java with Ant, JFrame Form.
Edit) Netbeans won't let you change the code that creates the objects.
So "private javax.swing.JButton a" this part is unchangeable.
Having that many individual JButtons seems like something you should try to avoid at all costs, especially if you have scenarios when you need to address them all, but if you are stuck with that you could do this:
JButton a = new JButton();
JButton b = new JButton();
//Etc for all the buttons you make
JButton[] list = {a,b}; //Manually insert the JButtons into an array
for(int i=0; i < list.length; i++) //For loop through all of the buttons in the list
{
list[i].addNotify(); //Then just use list[i] and that will be whatever JButton is at index i in the list (so in my example, i=0 is button a, i=1 is button b)
}
In the code above you insert all of your buttons into an array and then do the same function like I showed, where I called the .addNotify() function on every button in the list.
If you do have the opportunity to start from scratch and this would make things easier, I suggest putting all of the buttons into an array to begin with, such as the code below:
JButton[] list = new JButton[10]; //Manually insert the JButtons into an array
for(int i=0; i < list.length; i++) //For loop through all of the buttons in the list
{
list[i] = new JButton();
list[i].addNotify(); //Then just use list[i] and that will be whatever JButton is at index i in the list (so in my example, i=0 is button a, i=1 is button b)
}
Arrays are especially useful for these scenarios where you have a lot of objects of the same type and have the same operations done to them, so based on your description it might be a good application

Deep copies of 2d object array

how can I make on a button press a new deep copy of a 2 dimensional array?
Basically I created a game field with buttons. The game is called sokoban and it's a puzzle. The player is moving from one button to the other with arrow keys on a fixed map (8x8 buttons).
I want to implement an undo function. So I thought that I just create a deep copy of the JButton array before each move and save it into a stack. So when I press the undo button it calls the pop function of my stack. The problem is that I need to declare and initialize another JButton[][] where I can save the game field to before each move. Since I want infinite possible moves and also undos it seems impossible to me. I can't declare and initalize infite diffrent JButton[][] arrays. Any idea on how I can solve that?
That's how I copy a 2d object array:
JButton[][] tempArray = new JButton[jbArray.length][jbArray[0].length];
for (int i = 0; i < getJbArray().length; i++) {
for (int j=0;j<getJbArray()[0].length;j++) {
tempArray[i][j]=jbArray[i][j];
}
}
movesStack.push(tempArray);
Unfortunately you can't clone swing components in general, as they do not implement the Cloneable interface. As I see it you have two options:
Create a new JButton inside your double loop and copy whatever properties (like alignment, color etc.) you have set to the new JButton
Write your own class that extends JButton and implement the Cloneable interface
The first way is somewhat of a hack and not very robust or reusable. The second way is much better practice. In this case you'll have to define how the deep copy is supposed to happen, and ensure that all relevant properties are copied over.
You've got the right idea. You're not quite going deep enough.
public JButton[][] copy(JButton[][] jbArray) {
JButton[][] tempArray = new JButton[jbArray.length][jbArray[0].length];
for (int i = 0; i < jbArray.length; i++) {
for (int j = 0; j < jbArray[0].length; j++) {
tempArray[i][j] = new JButton(jbArray[i][j].getText());
}
}
return tempArray;
}
Rather than copying JButtons, you should have a model that you use to set the JButtons. Maybe a ModelClass[][] array?

Connect Four Java Game Project, need help on basic concepts

I am working on a lab, it's a connect four game. I'm having trouble specifically with basic concepts like how classes communicate with each other, how to use private instance variables, how to use an ArrayList, how to compare JLabels or set them as something comparable...
To give a brief breakdown I have four classes GUI, Game, Player, Name
I can create the GUI by using two four loops, the game is a grid with 7 columns of 6 pieces. The pieces are images,
JLabel Piece = new JLabel("images/blank.png");
for example to denote an empty spot.
The GUI is based on a JFrame, single content pane and four panels, one for a header which indicates who is playing and who won, another for the 7 buttons accompanying the 7 rows, the grid itself of the possible places to be played and then a button panel which gives you the option to replay.
I'm lacking in a lot of concepts. For instance, the replay button shouldn't appear until the game has ended.
I don't understand how to use an ArrayList. I tried to use
ArrayList<ArrayList<JLabel>> myList = new ArrayList<ArrayList<JLabel>>();
So when I create the GUI by running two for loops like so
For ( c = 0 ; c<8 ; c++) {
ArrayList<JLabel> column = new ArrayList<JLabel>();
For ( r = 0 ; r<7 ; r++) {
ArrayList<JLabel> row = new ArrayList<JLabel>();
JLabel empty = new JLabel("images/blank.png");
row.add(empty);
}
column.add(row);
}
Even this small step I've already got confused.
I know the two for loops above are not correct specifically the ArrayList.
I don't know how to create the arraylist and then use them.
using something like
column.get().get();
myList.get().get();
to get a specific piece.
I don't know how to pass that to an argument so that for example if I push on button 7 for column 7, and no pieces have been played yet, I can start from the lowest area column 7 row 6 and update that to a played piece, red or yellow for the appropriate player.
This is vague and I doubt I'll get anywhere but I am desperate for help. There isn't much time available from the TA's / Teacher and I believe I am lacking significantly to be able to finish this project.
I understand how it works/what I have to do in words but in terms of applying Java code...
I'd appreciate any help.
OK first off you should use an array of Enums. ArrayLists are intended for lots of items and that can have rapidly changing numbers. Arrays are intended to house data in a grid of some sorts. Since you are using a static board, use arrays! They are also much less memory-intensive. Example:
//Note you should use [column][row] as that is common practice.
States[][] grid = new States[7][6];
//And initialize it:
for(int i = 0; i < grid.length; i++)
for(int o = 0; o < grid[i].length; o++)
grid[i][o] = EMPTY_JLABEL;
Then declare an enum (this is a new class) (NOTE: replace FULL_PLAYER_ONE_JLABEL and FULL_PLAYER_TWO_JLABEL with the JLabels that have the image for each.):
public enum States {
FULL_PLAYER_ONE(FULL_PLAYER_ONE_JLABEL), FULL_PLAYER_TWO(FULL_PLAYER_TWO_JLABEL), EMPTY(EMPTY_JLABEL);
//The image of the appropriate state.
private JLabel label;
//Enum constructors must be private
private States(JLabel label) {
this.label = label;
}
public JLabel getLabel() {
return label;
}
}
In your GUI, have a JButton that is only added to the frame when the game is over. Also add a button to indicate when each column has been clicked by the player.
JButton button = new JButton();
//Initialize JButton and add to frame...
//Anytime before the frame is set to visible:
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
/* Perform tests for for what should happen.
For example test whose turn it is then call a method to add a piece to that column. Then call a checker to see if someone has won. If so, display the replay button, otherwise do nothing (allow other player to move).
*/
}
}

How to make a Jbutton array of images

I'm trying to build an array of JButton images. These will have a toggle (viewable/not viewable) thus why I chose to use JButtons.
These buttons also have a background image. When I place one button to the pane, this is in Java obviously, it works. But when I load the buttons in to an array and try to print them to the pane, nothing....I would appreciate the help. Here's what I have.
JButton card = new JButton();
JButton[] deck = new JButton[9];
int xLoc=20, yLoc=5;
card.setIcon(new ImageIcon("Back.jpg"));
card.setSize(200,250);
card.setVisible(true);
for(int i=0; i<9;i++)
{
deck[i]=card;
}
for(int i=1;i<10;i++)
{
deck[i-1].setLocation(xLoc,yLoc);
pane.add(deck[i - 1]);
validate();
xLoc+=220;
if(i%3==0)
{
yLoc+=265;
}
In my mind, I am creating a card object with a size and a background and visible, and then loading the same card over and over in to my array, then adding it to the pane, that has a background. It's not causing any errors or exceptions, but it's not placing anything but the background to the pane.
Thanks in advance. I will be honest and say this is a homework assignment, but I am exceeding the expectations by going this route. I know I can create individual buttons and put them on the screen. I know how, and can do it. What I want to do is not covered in the scope of the class.
This is a project, not just an assignment, and the instructor encouraged learning new things on our own and expanding the project. So, by helping me you are not helping me cheat, but helping me learn something more than the class teaches. Thanks!
Your basic problem comes down to the fact that a component can only reside within a single parent...
// You create a card...
JButton card = new JButton();
// You create an array of buttons
JButton[] deck = new JButton[9];
int xLoc=20, yLoc=5;
// You set the icon
card.setIcon(new ImageIcon("Back.jpg"));
// This is not a good idea...
card.setSize(200,250);
// JButton is visible by default...
card.setVisible(true);
// Start your loop...
for(int i=0; i<9;i++)
{
// Assign the card reference to an element in the array...
deck[i]=card;
// Add the card, via the array to the component...here's your problem...
pane.add(deck[i - 1]);
In adding card to pane, it is first removed from pane, as it can only have one parent. What you need to do, is assign a unique instance of JButton to each element in the array
// You create an array of buttons
JButton[] deck = new JButton[9];
// Start your loop...
for(int i=0; i<9;i++)
{
// Assign the card reference to an element in the array...
deck[i]=new JButton();
// You set the icon
deck[i].setIcon(new ImageIcon("Back.jpg"));
// This is not a good idea...
deck[i].setSize(200,250);
// JButton is visible by default...
deck[i].setVisible(true);
// Add the card, via the array to the component...here's your problem...
pane.add(deck[i]);
Now, I can't see from your code snippet, but it would appear you are trying to use a null layout, this is highly inadvisable. Instead, make the time to learn and understand how to use appropriate layout managers.
If you're not using a null layout or don't know what I'm talking about, then things like setSize and setLocation won't work the way you expect them to...

How to get a handle to all JCheckBox objects in order to loop?

I'm very new to Java and am having some issues looping through JCheckBoxes on a UI. The idea is that I have a bunch of checkboxes (not in a group because more than one can be selected.) When I click a JButton, I want to build a string containing the text from each selected checkbox. The issue I'm having is that our instructor told us that the checkboxes need to be created via a method, which means (see code below) that there isn't a discrete instance name for each checkbox. If there were, I could say something like
if(checkBox1.isSelected()) {
myString.append(checkBox.getText());
}
That would repeat for checkBox2, checkBox3, and so on. But the method provided to us for adding checkboxes to a panel looks like this:
public class CheckBoxPanel extends JPanel {
private static final long serialVersionUID = 1L;
public CheckBoxPanel(String title, String... options) {
setBorder(BorderFactory.createTitledBorder(BorderFactory
.createEtchedBorder(), title));
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
// make one checkbox for each option
for (String option : options) {
JCheckBox b = new JCheckBox(option);
b.setActionCommand(option);
add(b);
}
}
}
This is called like this:
toppingPanel = new CheckBoxPanel("Each Topping $1.50", "Tomato", "Green Pepper",
"Black Olives", "Mushrooms", "Extra Cheese",
"Pepperoni", "Sausage");
So I now have a panel that contains a border with the title "Each Topping $1.50", and 7 visible checkboxes. What I need to do is get a list of all the selected toppings. We are not supposed to use an ActionListener for each checkbox, but rather get the list when a button is clicked. I'm feeling really clueless here, but I just can't figure out how to get the isSelected property of the checkboxes when the individual checkboxes don't have instance names.
Ideally I'd like to somehow add all the checkboxes to an array and loop through the array in the button's action listener to determine which ones are checked, but if I have to check each one individually I will. I just can't figure out how to refer to an individual checkbox when they've been created dynamically.
I'm assuming you're not allowed to alter the CheckBoxPanel code at all. Which seems like a useless exercise, because in the real world, you'd think that if CheckBoxPanel where a class being provided to you (e.g. in a library) it would include a way of getting the selected options. Anyway, due to the limitation, you could do something like this:
for( int i=0; i<checkBoxPanel.getComponentCount(); i++ ) {
JCheckBox checkBox = (JCheckBox)checkBoxPanel.getComponent( i );
if( checkBox.isSelected() ) {
String option = checkBox.getText();
// append text, etc
}
}
I suggest you maintain a list of checkboxes:
List<JCheckBox> checkboxes = new ArrayList<JCheckBox>();
and before add(b) do:
checkboxes.add(b);
You may then iterate through the list of checkboxes in the buttons action-code using a "for-each" loop construct:
for (JCheckBox cb : checkboxes)
if (cb.isSelected())
process(cb.getText()); // or whatever.
Alternatively, if you need to keep track of the specific index:
for (int i = 0; i < checkboxes.size(); i++)
if (checkboxes.get(i).isSelected())
....
I would suggest that you dont put each of the checkboxes in a List when you create them. Instead, in your shared ActionListener, you maintain a Set of all selected checkboxes. Use the getSource method on the ActionEvent to identify which checkbox the user selected and then cast it to a JCheckBox. If isSelected() returns true for the item in question, attempt to add it to your selectedItems Set. If it is not, then attempt to remove it.
You can then just iterate over the subset of all items (only those that are selected) and print them to the console.

Categories

Resources