The code below is supposed to create and object instance for a specific type (say color) JButton I want to represent in a grid. When I iterate through the for-loop to add the buttons to the jframe it adds nothing. But if I add a single instance variable it will add that. Anybody have an idea?
public class Grid {
protected JButton [][] board;
private JButton player;
private JButton openCell;
private JButton wall;
private JButton closedCell;
public Grid(String [] args) { // args unused
// Instantiation
board = new JButton [6][6];
layout = new String [6][6];
blueCell = new JButton("BLUE CELL");
redCell = new JButton("RED CELL");
greenCell = new JButton("GREEN CELL");
whiteCell = new JButton("WHITE CELL");
// Configuration (add actions later)
// Decoration
blueCell.setBackground(Color.blue);
redCell.setBackground(Color.red);
greenCell.setBackground(Color.green);
whiteCell.setBackground(Color.white);
for (int rows = 0; rows < 6; rows++) {
for (int cols = 0; cols < 6; cols++) {
if ((layout[rows][cols]).equals('*')) {
board[rows][cols] = blueCell;
}
else if ((layout[rows][cols]).equals('.')) {
board[rows][cols] = redCell;
}
else if ((layout[rows][cols]).equals('x')) {
board[rows][cols] = greenCell;
}
else {
board[rows][cols] = whiteCell;
}
}
}
JFrame game = new JFrame();
game.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game.setLayout(new GridLayout (6, 6));
game.setSize(500, 500);
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board.length; j++) {
if ((board[i][j]).equals(blueCell)) {
grid.add(blueCell);
}
else if ((board[i][j]).equals(redCell)) {
grid.add(redCell);
}
else if ((board[i][j]).equals(greenCell)) {
grid.add(greenCell);
}
else {
grid.add(whiteCell);
}
}
}
grid.setVisible(true);
} // end of constructor
} // end of Grid class
You can add a component to your GUI only once. If you add it to another component, it will be removed from the previous component. You're trying to add the same JButtons several times, and that won't work. Instead you're going to have to create more JButtons. Consider having your buttons share Actions which is allowed.
If you need more help, consider posting compilable code (your current code is not), a small runnable, compilable program that demonstrates your problem, in other words, an sscce.
Edit
You comment:
But don't these count as instances of a JButton not the same JButton? (I don't understand what your answer meant...)
Think of it mathematically... how many JButtons do you create in your code above? Well, this is easy to figure, exactly 4:
blueCell = new JButton("BLUE CELL");
redCell = new JButton("RED CELL");
greenCell = new JButton("GREEN CELL");
whiteCell = new JButton("WHITE CELL");
So, now ask yourself, how many JButtons are you trying to display in your GUI with these four JButtons? If it's four, then you're possibly OK (as long as you use each button), but if it's more, then you're in trouble. From your 6x6 grid, board = new JButton [6][6];, it looks like you're trying to display 36 JButtons, and if this is true, you've got problems.
But again, if still stuck, please consider creating and posting an sscce.
Related
My assignment is to create 2 JPanels, one for a 2d array, 6 rows of 5 empty JTextFields and another for JButtons that should somewhat resemble an on-screen keyboard. I created the JPanels with the empty JTextFields and JButtons, now I need a way so that when I press a JButton with a letter from the alphabet it will assign that letter to the first available JTextField on the first available row and move one column at a time until the whole row is filled with letters (trying to add letters to a full row should do nothing). I also need to create a backspace button which I have that will remove the last letter (pressing backspace on an empty row should do nothing).
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Wordle extends JFrame implements ActionListener
{
private JPanel p1;
private JPanel p2;
private JTextField [][] g;
public Wordle()
{
setSize(500,300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
p1 = new JPanel();
p1.setLayout(new GridLayout(6, 5));
g=new JTextField [5][6];
for(int r=0; r<g.length; r++)
{
for(int c=0; c<g[r].length; c++)
{
g[r][c]= new JTextField();
getContentPane().add(g[r][c]);
p1.add(g[r][c]);
}
}
p2 = new JPanel();
p2.setLayout(new GridLayout(4, 7));
JButton a= new JButton("A");
a.addActionListener(this);
p2.add(a);
JButton b= new JButton("B");
b.addActionListener(this);
p2.add(b);
JButton c= new JButton("C");
c.addActionListener(this);
p2.add(c);
JButton d= new JButton("D");
d.addActionListener(this);
p2.add(d);
JButton e= new JButton("E");
e.addActionListener(this);
p2.add(e);
JButton f= new JButton("F");
f.addActionListener(this);
p2.add(f);
JButton g= new JButton("G");
g.addActionListener(this);
p2.add(g);
JButton h= new JButton("H");
h.addActionListener(this);
p2.add(h);
JButton i= new JButton("I");
i.addActionListener(this);
p2.add(i);
JButton j= new JButton("J");
j.addActionListener(this);
p2.add(j);
JButton k= new JButton("K");
k.addActionListener(this);
p2.add(k);
JButton l= new JButton("L");
l.addActionListener(this);
p2.add(l);
JButton m= new JButton("M");
m.addActionListener(this);
p2.add(m);
JButton n= new JButton("N");
n.addActionListener(this);
p2.add(n);
JButton o= new JButton("O");
o.addActionListener(this);
p2.add(o);
JButton p= new JButton("P");
p.addActionListener(this);
p2.add(p);
JButton q= new JButton("Q");
q.addActionListener(this);
p2.add(q);
JButton r= new JButton("R");
r.addActionListener(this);
p2.add(r);
JButton s= new JButton("S");
s.addActionListener(this);
p2.add(s);
JButton t= new JButton("T");
t.addActionListener(this);
p2.add(t);
JButton u= new JButton("U");
u.addActionListener(this);
p2.add(u);
JButton v= new JButton("V");
v.addActionListener(this);
p2.add(v);
JButton w= new JButton("W");
w.addActionListener(this);
p2.add(w);
JButton x= new JButton("X");
x.addActionListener(this);
p2.add(x);
JButton y= new JButton("Y");
y.addActionListener(this);
p2.add(y);
JButton z= new JButton("Z");
z.addActionListener(this);
p2.add(z);
JButton BackSpace= new JButton("<-");
BackSpace.addActionListener(this);
p2.add(BackSpace);
JButton Enter= new JButton("[");
Enter.addActionListener(this);
p2.add(Enter);
this.getContentPane().add(p1,BorderLayout.NORTH);
this.getContentPane().add(p2,BorderLayout.SOUTH);
this.setVisible(true);
}
public void actionPerformed(ActionEvent e) //need help with
{
if(e.getSource().equals("A"))
{
for(int r=0; r<g.length; r++)
{
for(int c=0; c<g[r].length; c++)
{
g[r][c].setText("A");
}
}
}
}
public static void main(String[] args)
{
new Wordle();
}
}
This is my code and my main issue is setting the text in the 2d array of JTextFields using actionlistener, I don't mind doing each if loop for each letter individually as long as it makes sense and works the way I intended it to, btw if you haven't already noticed this is the game "Wordle" I am trying to make, I'm still a newbie programmer and all of this is new to me so some kind of intuitive explanation would be much appreciated.
This line if(e.getSource().equals("A")) is your first issue. It simply will not work because e.getSource() returns an object that will never equal "A".
Instead, you need to first cast the source to the correct object type like so:
public void actionPerformed(ActionEvent e) //need help with
{
JButton clicked = (JButton)e.getSource();
Now we can now get the text from the button using use getText() like this (Although there is a smarter solution we can use down below):
public void actionPerformed(ActionEvent e) //need help with
{
JButton clicked = (JButton)e.getSource();
if(clicked.getText().equals("A")) {
...
The next issue you face is how you store the data, you need to track the current cell using a class variable, rather than just filling up the whole array:
private int row = 0;
private int column = 0;
Then all together the changes might look a bit like this:
//Class variables
private int row = 0;
private int column = 0;
public void actionPerformed(ActionEvent e) //need help with
{
//Cast the event source to a button
JButton clicked = (JButton)e.getSource();
//Handle backspace
if(clicked.getText().equals("<-"))
{
//Decrease the tracking number
column--;
//Make sure that only valid cells are back spaced
if(column < 0)
{
column = 0;
}
//Set the cell to be blank
g[row][column].setText("");
}
//Handle enter
else if(clicked.getText().equals("["))
{
//Add your behaviour here
....
//Finally move to the next row
row++;
}
//Handle the rest of the letter buttons here
else
{
//We don't need `for` loops, we can just directly add the letter from
//the clicked button to the correct place in the array like so
g[row][column].setText(clicked.getText);
//Increment the tracking numbers
column++;
//Move to the next row when the column value is over 5:
if(column > 4)
{
//Move to the next row
row++;
//Reset the column number to 0
column = 0;
}
}
}
I am working in the Treasure Hunt Game Project for my java class, I got super confused when the professor asked me to do this "Do not use instanceof, or break, except inside switch statements."
currently inside the functions i am using if and for statements.
Can i change it so i can get rid of intanceof?
In the button part I am using if(. . . intanceof. . . )
Can i do it with try and catch? instead of if? if so how?
Treasure Game
import java.awt.*;
import java.util.Random;
import javax.swing.*;
public class TreasureBoardPanel extends JPanel
{
private static final int WIDTH = 10;
private static final int HEIGHT = 10;
// Instance variables
private BoardButton[] button; //used to add the button to the panel
private TreasureGame game; //used to make make the constructor for the TreasureBoardPanel
//Costructor
public TreasureBoardPanel(TreasureGame game)
{
super();
this.game = game;
//setting the layout
setLayout(new GridLayout(WIDTH, HEIGHT));
//adding the buttons
addButtons();
}
//Create and adding buttons to panel
private void addButtons()
{
this.button = new BoardButton[WIDTH * HEIGHT];
//creating the random buttons
Random random = new Random();
for (int i = 0; i < TreasureGame.NUM_TREASURES; i++)
{
int index = random.nextInt(this.button.length);
//Check if index is already a button
while (this.button[index] != null)
index = random.nextInt(this.button.length);
this.button[index] = new TreasureButton();
}
// For all the buttons which are not TreasureButton i.e. null buttons
// create BoardButton
for (int i = 0; i < this.button.length; i++)
{
if (this.button[i] == null)
this.button[i] = new BoardButton();
}
// Add all buttons to the panel and add action listener
for (int i = 0; i < this.button.length; i++)
{
this.button[i].addActionListener(new ButtonListener(game));
add(this.button[i]);
}
}
//Display text from all treasures method
public void displayAllTreasures()
{
for (int i = 0; i < this.button.length; i++)
{
if (this.button[i] instanceof TreasureButton)
this.button[i].setText(this.button[i].getDisplayText());
}
}
}
The point your professor was making wasn't to replace if with switch, but to avoid using instanceof in the first place and use polymorphism instead. Usually you can just add a method to the object's class which either handles the task itself or returns the information needed for the task, and override it in subclasses.
In this case, you could add a method to BoardButton called isTreasure that returns false, and have TreasureButton override it to return true. Then you can just call btn.isTreasure() instead of checking which class it is.
Beginner Java programmer here. I'm trying to create a card game to learn more about Java. I have an array of names I pulled out a database. For each String in the array I want to create a JPanel and inside JLabels where I will set the name, power, health, etc.
The problem is when I create these in a loop they all have the same name and overwrite each other. Since I read Java doesn't have dynamic Variable names, how do I solve this?
public void loadDatabaseCardElements(ArrayList cards) {
ArrayList<String> buildCards = cards;
int i;
for(i = 0; i != buildCards.size();) {
String var = buildCards.get(0);
//create the Panel etc
JPanel mainHolder = new JPanel();
mainHolder.setLayout(new BoxLayout(mainHolder, BoxLayout.PAGE_AXIS));
JLabel name = new JLabel("Name: " + var);
JLabel powerLabel = new JLabel("Power: ");
JLabel healthLabel = new JLabel("Health: ");
JLabel armorLabel = new JLabel("Armor: ");
JLabel type1Label = new JLabel("Type1");
JLabel type2Label = new JLabel("Type2: ");
JLabel ability1Label = new JLabel("Ability1: ");
JLabel ability2Label = new JLabel("Ability2: ");
JLabel ability3Label = new JLabel("Ability3: ");
JButton card1 = new JButton("Add to deck");
mainHolder.add(name);
mainHolder.add(powerLabel);
mainHolder.add(healthLabel);
mainHolder.add(armorLabel);
mainHolder.add(type1Label);
mainHolder.add(type2Label);
mainHolder.add(ability1Label);
mainHolder.add(ability2Label);
mainHolder.add(ability3Label);
mainHolder.add(card1);
mainHolder.setBorder(BorderFactory.createLineBorder(Color.black));
mainHolder.setPreferredSize( new Dimension( 130, 200 ) );
frame1.add(mainHolder, BorderLayout.WEST);
SwingUtilities.updateComponentTreeUI(frame1);
card1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
preDeck.add(var); //add to another array when clicked
}
});
if (buildCards.size() != 0) {
buildCards.remove(0);
} else {
}
}
}
The reason for overwriting all the panels with same name is due to this part of your code:
int i;
for(i = 0; i != buildCards.size();) {
String var = buildCards.get(0);
You are assigning the first element of your list to each JLabel. This could help you achieve what you need:
for(int i = 0; i < buildCards.size(); i++){
String var = buildCards.get(i);
// Followed by your code
}
set a growable layout for a standard jpanel in the frame and then add a new jpanel to the standard jpanel every time. this should solve the naming problem. if u need access to each panel, you can store them in an array
I have a questions about using array
I have a method that creates JButton for a JPanel. I used JButton[] to store 7 buttons in it.
The problem is those buttons must be setEnable(false) initially. they are only enabled when openButton is clicked.
I would like to create another method that just take all elements from JButton[] and set them Enable. How can I do that?
private JButton filterButtons() {
//set layout for buttons
setLayout(new BorderLayout());
//Array to store description of buttons
final String[] filterNames = {myEdgeDetect.getDescription(),
myEdgeHighlight.getDescription(),
myFlipHorizontal.getDescription(),
myFlipVeritcal.getDescription(),
myGrayscale.getDescription(),
mySharpen.getDescription(),
mySoften.getDescription()};
final JButton[] filterButtons = new JButton[filterNames.length];
//This panel store buttons on north
final JPanel buttonPanel = new JPanel();
//Start to print buttons
for (int i = 0; i < filterNames.length; i++) {
filterButtons[i] = new JButton(filterNames[i]);
filterButtons[i].setEnabled(false);
filterButtons[i].addActionListener(null);
filterButtons[i].setActionCommand(" " + i);
buttonPanel.add(filterButtons[i]);
}
If, rather than defining filterNames and filterButtons inside the method you made them fields of the class, then it would be easy to write a second method that iterates through the filterButtons and enables them.
Class Whatever {
String[] filterNames;
JButton[] filterButtons;
private JButton filterButtons() {
//set layout for buttons
setLayout(new BorderLayout());
//Array to store description of buttons
filterNames = {myEdgeDetect.getDescription(),
myEdgeHighlight.getDescription(),
myFlipHorizontal.getDescription(),
myFlipVeritcal.getDescription(),
myGrayscale.getDescription(),
mySharpen.getDescription(),
mySoften.getDescription()};
filterButtons = new JButton[filterNames.length];
//This panel store buttons on north
final JPanel buttonPanel = new JPanel();
//Start to print buttons
for (int i = 0; i < filterNames.length; i++) {
filterButtons[i] = new JButton(filterNames[i]);
filterButtons[i].setEnabled(false);
filterButtons[i].addActionListener(null);
filterButtons[i].setActionCommand(" " + i);
buttonPanel.add(filterButtons[i]);
}
}
void enableButtons() {
for (int i = 0; i < filterButtons.length; i++) {
filterButtons[i].setEnabled(true);
}
}
}
I am trying to create dynamic JButton and JLabel based on the number of URLs defined in the properties file.
What I have tried so far is:
AppResources.properties file
urls=http://google.com,http://stackoverflow.com,http://gmail.com
urlLabels=Internet Users,MPLS Users,Physical Access (Not Advised)
In my Java program I am reading the properties file and based on the comma separator splitting the string and now i need to generate the buttons and labels accordingly. Like the first URL Label --> first URL as Button and so on.
The way I have done this so far is:
String url = properties.getProperty("urls");
String urlLabel = properties.getProperty("urlLabels");
String[] jButton = url.split(",");
String[] jLabel = urlLabel.split(",");
for (int i = 0; i < jLabel.length; i++) {
JLabel labels = new JLabel(jLabel[i]);
panel.add(labels);
for (int j = 0; j < jButton.length; j++) {
JButton button = new JButton(jButton[j]);
panel.add(button);
}
}
But it prints the button three times for a label. How to fix this? Also how to write the action listeners for these buttons?
If you want to implement action listeners for your buttons, you can simply create and add a new ActionListener while creating the button.
Example :
for (int i = 0; i < jLabel.length; i++) {
final String str = jLabel[i];
JLabel labels = new JLabel(str);
panel.add(labels);
JButton button = new JButton(jButton[i]);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(panel, str);
}
});
panel.add(button);
}
Remove the inner loop (j based).