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
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 want to add mouseListener to all labels in the array. Every label should show an other card of the layout. If I use below code, all labels show card6. What is wrong?
sorry this is correct code..
panList = new JPanel();
panList.setBounds(0, 0, 206, 517);
panList.setLayout(null);
cs.add(panList);
CreateCards();
int y = 0;
for(i = 0 ; i < 6; i++) {
String lblName = getString("lbl"+String.valueOf(i));
lblSettingTitle[i] = new JLabel(" "+lblName);
lblSettingTitle[i].setBounds(0, y+10, 206, 26);
lblSettingTitle[i].addMouseListener(new MouseListener() {
public void mouseClicked(MouseEvent e) {
CardLayout cardLayout = (CardLayout) cards.getLayout();
cardLayout.show(cards, "card"+String.valueOf(i));
}
});
panList.add(lblSettingTitle[i]);
y+=26;
}
}
private void CreateCards() {
card1 = new JPanel();
card2 = new JPanel();
cards = new JPanel(new CardLayout());
cards.setBounds(206, 35, 814-206, 546-120);
cs.add(cards);
cards.add(card1, "card1");
cards.add(card2, "card2");
}
the problem is when mouse-event fire value of i have value 6 or last value of for-loop
for (i = 0; i < 6; i++){}
you can create a jlable class and give a instance variable like lableindex
so when mouse-event occurs you first get the lable index and then show corresponding card.
or
you can getname of the jlable and get index by removing lbl part of the jlable name and show corresponding card.for example if jlable name is lb12 then take 2 out and show card named card + 2 or card2
for example consider this example
public void mouseClicked(java.awt.event.MouseEvent e) {
String index = ((JLabel)e.getSource()).getText().substring(xx,yy); // here xx , yy depend on how you are naming jlables .this should return 2 if your lable is lbl2
CardLayout cardLayout = (CardLayout) cards.getLayout();
cardLayout.show(cards, "card" + index);
System.out.println("card" + index);
}
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 add the contents of two arrays to two TextFields. When you run the program the problem is the current TextFields that I try to display (lines 70 - 83) when the window is redrawn, they only show the last item in their array. Is there any way to add all the items in a stacked list (one ontop of another.)
This is my first class ClassNameSorting
Code:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
public class ClassNameSorting extends JFrame {
JTextField studentNameInputFirst, studentNameInputLast, studentNamesEneteredLast, studentNamesEnteredFirst;
JButton nextName, sort, backToStart;
JLabel firstName, lastName, classList;
String disp = "";
ArrayList<String> studentNameFirst = new ArrayList<String>();
ArrayList<String> studentNameLast = new ArrayList<String>();
ArrayList<String> sortedStudentNameFirst = new ArrayList<String>();
ArrayList<String> savedUnsortedStudentNameLast = new ArrayList<String>();
Container container = getContentPane();
public ClassNameSorting() {
container.setLayout(new FlowLayout());
studentNameInputFirst = new JTextField(15);
studentNameInputLast = new JTextField(15);
nextName = new JButton("Save");
sort = new JButton("Sort");
firstName = new JLabel("First Name: ");
lastName = new JLabel("Last Name: ");
nextName.setPreferredSize(new Dimension(110, 20));
sort.setPreferredSize(new Dimension(110, 20));
container.add(firstName);
container.add(studentNameInputFirst);
container.add(lastName);
container.add(studentNameInputLast);
container.add(nextName);
container.add(sort);
nextName.addActionListener(new nextNameListener());
sort.addActionListener(new sortListener());
setSize(262, 120);
setVisible(true);
}
private class nextNameListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
studentNameFirst.add(studentNameInputFirst.getText());
studentNameLast.add(studentNameInputLast.getText());
studentNameInputLast.setText(null);
studentNameInputFirst.setText(null);
}
}
private class sortListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
savedUnsortedStudentNameLast = new ArrayList<String>(studentNameLast);
Collections.sort(studentNameLast);
int totalSizeOfArray = studentNameLast.size();
for(int i = 0; i < totalSizeOfArray; i++){
boolean containsYorN = false;
String tempElementForContains = studentNameLast.get(i);
String tempElementFromStudentNameLast = savedUnsortedStudentNameLast.get(i);
containsYorN = savedUnsortedStudentNameLast.contains(tempElementForContains);
if(containsYorN == true){
int tempIndexPos = savedUnsortedStudentNameLast.indexOf(tempElementForContains);
String tempIndexElement = studentNameFirst.get(tempIndexPos);
sortedStudentNameFirst.add(i, tempIndexElement);
}
}
studentNamesEneteredLast = new JTextField();
studentNamesEnteredFirst = new JTextField();
for(int i = 0; i < totalSizeOfArray; i++){
studentNamesEneteredLast.setText(studentNameLast.get(i));
}
for(int i = 0; i < totalSizeOfArray; i++){
studentNamesEnteredFirst.setText(sortedStudentNameFirst.get(i));
}
studentNamesEneteredLast.setEditable(false);
studentNamesEnteredFirst.setEditable(false);
container.add(studentNamesEneteredLast);
container.add(studentNamesEnteredFirst);
setSize(262, 500);
revalidate();
}
}
}
My second class is: (DrawMainWindow)
import javax.swing.JFrame;
public class DrawMainWindow {
public static void main(String[] args) {
ClassNameSorting drawGui = new ClassNameSorting();
drawGui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
drawGui.setLocationRelativeTo(null);
}
}
The first array is studentNameLast. I am trying to add that to studentNamesEnteredLast text field. The second is sortedStudentNameFirst being added to studentNamesEnteredFirst.
Thanks for the help!
for(int i = 0; i < totalSizeOfArray; i++){
studentNamesEneteredLast.setText(studentNameLast.get(i));
}
The text in the JTextField will only reflect the last item of the List. If you wish to append the entire list, create a String from the List and set the text of the JTextField with that String (you might wish to have them separated by some character - below uses a comma)
StringBuilder sb = new StringBuilder();
for(int i = 0; i < totalSizeOfArray; i++){
sb.append(studentNameLast.get(i)).append(",");//comma delim
}
studentNamesEneteredLast.setText(sb.toString());
Not entirely sure what you are after, but a JList or JTable might be more appropriate to display List information
Was able to switch to a GridLayout and then added each last name and then first name together.
Code:
container.setLayout(new GridLayout(totalSizeOfArray+3,2));
for(int i = 0; i < totalSizeOfArray; i++){
studentNamesEnteredLast = new JTextField();
studentNamesEnteredFirst = new JTextField();
studentNamesEnteredFirst.setEditable(false);
studentNamesEnteredLast.setEditable(false);
studentNamesEnteredLast.setText(studentNameLast.get(i));
studentNamesEnteredFirst.setText(sortedStudentNameFirst.get(i));
container.add(studentNamesEnteredLast);
container.add(studentNamesEnteredFirst);
}
Example:
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.