JLabels with JTextFields in LinkedHashMap - java

I have a program that at one part demands a user to determine the amount of days per week in 40 weeks (def = 5).
The user firstly fills in the amount of days the 40 weeks will have, to then set the days per week.
Now, I have both JLabel (KEY) and JTextfield (VALUE) stored in a LinkedHashMap,
LinkedHashMap<JLabel, JTextField> weeksMap = new LinkedHashMap<JLabel,JTextField>();
for (int i=1; i<=40; i++) {
JLabel weekL = new JLabel("Week "+i);
JTextField weekF = new JTextField(10);
weekF.setText("5");
//SetWeekAction sWA = new SetWeekAction(mainPane, weekL, weekF);
//weekF.addActionListener(sWA);
weeksMap.put((weekL), weekF);
}
and they will be added to the panel after user sets the total amount of days in the certain year.
EDIT - NOTE: the reason for having these two in a HashMap is I cannot create elements on lick, otherwise I could create infinite labels and text fields and I do not wish to work with buttonpressed=true or such. I need both text fields and labels 'prepared' before the 'click' happens.
for (Map.Entry<JLabel, JTextField> entry : weeksMap.entrySet()) {
index++;
weeksPane.add(entry.getKey());
weeksPane.add(entry.getValue());
}
The GUI view
How do I get the text field of for example 'Week 23'? The for loop goes through the List and adds the Objects correctly, but I have no reference to that certain object anymore.

You can use one ArrayList for storing text field and label text
ArrayList<JTextField> weeks = new ArrayList<JTextField>();
for (int i=1; i<=40; i++) {
JTextField weekF = new JTextField(10);
weekF.setName("Week "+i);
weekF.setText("5");
JLabel weekL = new JLabel(weekF.getName());
weekL.setLabelFor(weekF);
weeks.put(weekF);
}
On update event you can invalidate and redraw weeks panel

I can think of one simple solution of making two separate LinkedHashMap one as LinkedHashMap < integer, JLabel> and another as LinkedHashMap
Now in your loop you can add value in both the LinkedHashMap using the int value from loop as key for JLabel and JTextField while storing them in your both LinkedHashMap.
Since both JLabel and JTextField are now attached with the integer value according to the loop number in which they were created you can access them using those integer value.
Hope this can solve your problem.

Related

Programmatically Name Variables in Java for GUI

I am creating a GUI in java using gridLayout 6 x elevatorNum. My purpose is to create the number of columns based on the user input "elevatorNum" so that it can automatically be expanded. My problem now is that I want to populate each column with the same 6 JLabel fields and then be able to use these fields to change their values whenever I want to.
I am not able to do this since I will have to create a new set of 6 JLabels for each column but for that I would need to either hardcode each column or automatically expand them using user input. I want to automatically expand them using userInput but I don't know how to name each set of 6 JLabels without hardcoding them.
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 300);
frame.setLayout(new GridLayout(7,elevatorNum));
JLabel totalFloors = new JLabel("Total floors: " + floorNum);
JLabel currentFloor = new JLabel("CurrentFloor : N/A");
JLabel destFloor = new JLabel("Destination Floor: N/A");
JLabel doorStatus = new JLabel("Doors Status: N/A");
JLabel motorStatus = new JLabel("Motor Status: N/A");
JLabel passengerStatus = new JLabel("Passenger Status: N/A");
JLabel elevatorStatus = new JLabel("Elevator Direction: N/A");
frame.add(totalFloors);
frame.add(currentFloor);
frame.add(destFloor);
frame.add(doorStatus);
frame.add(motorStatus);
frame.add(passengerStatus);
frame.add(elevatorStatus);
Now i want to create another 6 set of JLabels but I will have to use different name but I don't know the userinput so I cannot hardcode the 6 JLabels. I also want to use each set of JLabels later on to update/edit their values.
I would greatly appreciate your help.
I had a similar experience of populating the layout with buttons and need to change their values anytime I want. I think you don't need to have user input to create labels, try simply create JLabels in a for loop, and track them by adding each of them to a List. you could find exactly that label through its index in array.
for example, create a list to track them:
List<JLabel> labelList = new ArrayList<>();
then create a method to create JLabels:
private JLabel createLabel() {
JLabel newLabel = new JLabel("give_it_an_initial_name");
// maybe do something on each label
return newButton;
}
finally add them to frame:
for(int i = 0; i < 6 * elevatorNum; i++) {
JLabel addLabel = createLabel();
frame.add(addLabel);
labelList.add(addLabel);
}
when you want to change something on label, fetch it from list and edit, no need to give each of them a name.It's a very simple way, might not be very good, but it works.

I have a list of JTextField references. Is there any way to initialize those through an array?

ArrayList<JTextField> listTxt=new ArrayList<>(Arrays.asList(
txtVel1,txtVel2,txtVel3,txtVel4,txtVel5,txtVel6,
txtVel7,txtVel8,txtVel9,txtVel10,txtVel11,
txtVel12,txtVel13,txtVel14,txtVel15,txtVel16,
txtVel17,txtVel18,txtVel19,txtVel20));
Is there any way to initialize these JTextField through a loop, or do I need to go one by one?
Are you looking for something like this:
ArrayList<JTextField> listTxt=new ArrayList<>();
for(int i=0; i<20; i++){
listTxt.add(new JTextField());
}
You can use a stream/map operation, though ote that the swing API has a lot of old dinosaurs in there which don't always play nice with the new toys that java 8 brought. Still, this should work:
var textFields = List.of(txtVel1, txtVel2, txtVel3).stream()
.map(JTextField::new).collect(Collectors.toList());
now textFields is a variable referencing a list of JTextField instances, each initialized with one of the strings.

I need to make a reference to a JLabel based off a string

So I have numbered JLabels declared like so (In the class)
OP_1
OP_2
OP_3
etc..
And I have a number and a string.
What I want is that when, for example, the number is 2. I want to change the label text to the content of the string. This is part of a method that is supposed to take a string, put it into the last available JLabel, and then increment the number.
I am very confused, and help would be appreciated.
Here I created an array of JLabels and a method, updateNextLabel(String), which will update the next JLabel with whatever you enter for str.
public class Example {
static int count = 0; //Create a count
static JLabel[] array = new JLabel[3]; //Create an array to hold all three JLabels
public static void main(String[] args) {
//Set the default text for each JLabel
array[0] = new JLabel("This is OP1");
array[1] = new JLabel("This is OP2");
array[2] = new JLabel("This is OP3");
//Here is an example if you wanted to use a for-loop to update the JLabels
for (int x = 0; x < array.length; x++) {
updateNextLabel("This is the new text for OP" + (count + 1));
System.out.println(array[x].getText());
}
}
public static void updateNextLabel(String str) {
array[count].setText(str);
count++;
}
}
Instead of / additional to naming your labels by specific names you can later match them on, I'd think a Map of JLabels with Strings or Integers as keys might be a better approach:
Map<String,JLabel> labelMap = new HashMap<String,JLabel>();
labelMap.put("1", OP_1);
labelMap.put("2", OP_2);
This will allow later access of "The label for key 2" as well as "list me all that labels and find the one with text 2" as well

GridLayout columns

I recently decided to start using GridLayout because FlowLayout seems somewhat amateur. However, I need help. The parameters when creating the GridLayout are (rows,columns,row space,column space). I have a variable for the row amount and 4 for the column amount, but when I try to add a JButton after everything else, there are 5 columns.
Here is my code:
byte i = 0;
while(i < main.componentNum)
{
comp[i] = new JLabel("component #" + (i+1));
box[i] = new JComboBox();
field[i] = new JTextField(5);
edit[i] = new JButton("edit");
comp[i].setBackground(Color.WHITE);
box[i].setBackground(Color.WHITE);
field[i].setBackground(Color.WHITE);
edit[i].setBackground(Color.WHITE);
add(comp[i]);
add(box[i]);
add(field[i]);
add(edit[i]);
i++;
}
When I run the above code, I get four columns and it works fine. But when I add a button to the end, I get five. Can anyone tell me how to give one button an entire row?
From the Java Docs
One, but not both, of rows and cols can be zero, which means that any
number of objects can be placed in a row or in a column.
Now, without your actual code the sets up the GridLayout, it's difficult to say, but, if your after maintaining only 4 columns, I would create a GridLayout as follows, new GridLayout(0, 4)
If you want something more flexible, look into GridBagLayout

How to print to a J text box the entire contents of a tree map?

Hi Everyone thanks for taking the time to look at my question.
I would like to use the JText field I have created to display the values of a tree map which contains all the employees: ID numbers (as the key in the map)as well as an Employee object which contains a to string method of all the employee details.
the system seems to be working fine because when I print to the console (CMD) it works fine and prints out all the values in the MAP but when I try print it to a JText box it only prints one object (one employee) from the entire list.
I believe the issue lies with my for loop i am using to access all the details.
the issue lies with this line of code:
writeStrings.setText(writeStrings.getText()+" "+dEmp);
This is the code in its entirety:
public void chooseEmpToAdd()
{
JFrame frameAllEmps = new JFrame();
frameAllEmps.setSize( 450, 140 );
frameAllEmps.pack();
frameAllEmps.setVisible(true);
int x = 0;
System.out.println("ALL Emps from the tree map");
for(int key:employeeMap.keySet())
{
JTextField writeStrings;
writeStrings = new JTextField(20);
Employee dEmp = employeeMap.get(key);
System.out.println("Employe no :" +x+": "+dEmp);
writeStrings.setText(writeStrings.getText()+" "+dEmp);
frameAllEmps.add(writeStrings);
x++;
}
}
writeStrings = new JTextField(20);
You create new JTextField component on every iteration and add it to container.
JFrame uses BorderLayout as a default layout.
This layout puts your JTextField component in the center (frameAllEmps.add(writeStrings)). So you lost previous added JTextField and see only last JTextField component.

Categories

Resources