Working on a GUI in Eclipse using WindowBuilder and ran into a roadblock..
I've created a JWindow with a drop-down box intended to display a list of people from a people array. The structure of my classes are:
public class Person {
String name;
int age;
ArrayList<Goal> goals;
}
public class Goal {
String name;
int daysToComplete;
}
Within this JWindow GUI, the drop-down box lists out all of the Person instances. Once I select a person (let's say Bob) - I want to dynamically create labels and JTextAreas to list out Bob's attribute values, for example:
Name: Bob
Age: 20
Goals:
- Goal 1, complete in X days
- Goal 2, complete in Y days
and so on.. I don't want to statically add 3 labels (Name, Age, Goals) and their respective JTextAreas (Bob, 20, Goal 1/Goal 2), because the structure of Person will likely change in the future.
What is the best way to do this?
Thanks!
If I'm understanding you correctly, you can get what you want by creating anonymous instances of JLabel and JTextArea and placing them into an array list. I don't know the specifics of your environment, but hopefully, you can follow the idea:
ArrayList<JLabel> nameLabelList = new ArrayList<JLabel>();
ArrayList<JLabel> ageLabelList = new ArrayList<JLabel>();
ArrayList<Goal> goalList = new ArrayList<Goal>();
// Event handler method
public void personSelected(person)
{
nameLabelList.add(person.name);
ageLabelList.add(person.age);
// This assumes each person has a single goal. You can adapt the code
// for multiple goals easily
goalLabelList.add(person.goal);
}
Then, after the lists are created, all you have to do is loop through these array lists and spit them out into your UI:
for(int counter = 0; counter < nameLabelList.size; counter++)
{
myContainer.add(nameLabelList.get(counter));
myContainer.add(ageLabelList.get(counter));
myContainer.add(new JLabel(goalList.get(counter).toString()));
}
After adding the contents of the array lists, make sure that they show up in the UI:
myContainer.revalidate();
myContainter.repaint();
You will have to add new Panels to your Main Panel. So your Main Panel should provide a scrollable inner Panel to which you add new lines. If you have ever worked with HTML and Tables you will understand what I am talking about.
Once you got this attribute-show-panel (inner Panel), you can load as many attributes into it with a for loop as you want.
The code would technically be like for each goal in goalArray -> add new linePanel to attribute-show-panel.
whereas a linePanel yould store a label, abutton, etc and many line Panels would list vertically
Related
I am developing an application in Netbeans using Java and have been told to use the GUI creation features that Netbeans offer. Due to this I cannot edit the initComponents(); method to edit the creation of the JList and add a default list model to it.
I have tried creating a new JList but that resulted in an infinite loop. I haven't ever created controls through coding them myself, only by an IDE's GUI creation tools.
This is what I have currently:
private void formWindowActivated(java.awt.event.WindowEvent evt) {
//String to hold current patients data
String patientDetails;
//Take the arraylist from the model
ArrayList<IAccountStrategy> unapprovedPatients;
unapprovedPatients = model.getObservers();
//Create default list model to store the patients details
DefaultListModel<String> unapprovedPatientModel = new DefaultListModel<>();
IAccountStrategy xx;
//For loop to iterate through each element of unapprovedPatients
for(int i = 0; i < unapprovedPatients.size(); i++){
//get the current patients details and store them in a string variable
xx = unapprovedPatients.get(i);
patientDetails = xx.getAccountID() + xx.getUsername() + xx.getFirstname() + xx.getLastname();
//Add string variable to list model
unapprovedPatientModel.addElement(patientDetails);
}
//add list model to existing JList
listPatients.addElement(unapprovedPatientModel);
}
I would like to output all the elements from the list model into the actual JList and then let the user interact with the list itself.
Thanks in advance!
is it not possible to use the list as I want
You just wrote code to create the DefaultListModel.
So now all you need is to add:
list.setModel( unapprovedPatientModel );
so the JList can use the newly created model.
Although the problem with this code is that the code will be executed every time the window is activated.
But the point is that all you need to do is update the list using the setModel() method. How you do this in the IDE is up to you.
I have two sets of Objects, first stores Labels and the second one stores Buttons. Every label is connected to its own button i.e label11 is placed on btn11 and so on. I want to change visibility of labels if I click its button. I managed to do this in this way:
btn11.setOnAction(x->label11.setVisible(true));
btn12.setOnAction(x->label12.setVisible(true));
btn21.setOnAction(x->label21.setVisible(true));
btn22.setOnAction(x->label22.setVisible(true));
btn111.setOnAction(x->label111.setVisible(true));
btn112.setOnAction(x->label112.setVisible(true));
btn121.setOnAction(x->label121.setVisible(true));
btn122.setOnAction(x->label122.setVisible(true));
Doing this way I have to write every single line one by one which makes my code unnecessary long and hard to read.I tried placing them into two lists but couldn't find a way to iterate through two lists in one loop.
So far I managed to create something like this:
for(int i=0;i<listOfButtons.size();i++){
listOfButtons.get(i).setOnAction(x->listOfLabels.get(i).setVisible(true));
}
But I'm getting error which says that variables in lambda expressions should be final.
I'd be glad for any help.
Thank you in advance.
Assign the values you need to a final variable before using it in the lambda. This will also increase readability.
for (int i = 0; i < listOfButtons.size(); i++) {
final Button button = listOfButtons.get(i);
final Label label = listOfLabels.get(i);
button.setOnAction(x -> label.setVisible(true));
}
You can do it in a "smooth"-er way by utilizing some additional Java 8 functionality instead of the traditional for and final declarations which should be resolving an issue with i and can therefore be fixed with final int fi = i; and use the final one instead in your lambda. Or this:
IntStream.range(0, buttons.size())
.forEach(i -> buttons.get(i).setOnAction(e -> labels.get(i).setVisible(true)));
Additionally, given your example of poorly named label and button references, I would also suggest you put the pair in a convenience class and a single list of the components.
class ButtonLabelPair {
Button button;
Label label;
}
List<ButtonPairs> buttonPairs = ...
And set the actions like:
buttonPairs.forEach(p -> p.button.setOnAction(e -> p.label.setVisible(true)));
Or, you could do it in the constructor of the pair:
class ButtonLabelPair {
...
public ButtonLabelPair(Button button, Label label) {
this.button = button;
this.label = label;
this.button.setOnAction(e -> this.label.setVisible(true));
}
}
I'm trying to build a dynamic web app in GWT, when widgets are added to the screen I remember their 'name' by setting the Widget.setId, when I want to replace part of the page, I can find the element in question via DOM.getElementById('name'), and its parent using DOM.getParentElement(), and then remove its children.
Now I have a com.google.gwt.dom.client.Element object (the parent). What I want to do is turn this back into a GWT object - in fact it'll be something derived from Panel, so I can add additional Widgets.
How do I go from the Element object back to a Panel object ?
I totally accept I could be going about this the wrong way, in which case is there a better way?
I think your approach to remove widgets from the DOM using DOM.getElementById('name') is not the proper one.
On your case (I am just figuring out what you do), I would keep Java Objects references instead of accessing to them using the DOM.
For instance:
HorizontalPanel panel = new HorizontalPanel();
Widget w = new Widget();
//We add the one widget to the panel
panel.add(w);
//One more widget added
w = new Widget();
panel.add(w);
//Now we remove all the widgets from the panel
for(int i = 0; i < panel.getWidgetCount(); i++){
panel.remove(panel.getWidget(i));
}
UPDATE
Based on your comments, I would propose the following solution.
I suppose that you are storing widgets on HorizontalPanel, just apply this solution to your concrete case.
I propose to use customized class which inherits from HorizontalPanel and add a Map there to store relationship between names and widgets.
public class MyHorizontalPanel extends HorizontalPanel {
private Map<String, Widget> widgetsMap;
public MyHorizontalPanel(){
super();
widgetsMap = new HashMap<String, Widget>();
}
//We use Map to store the relationship between widget and name
public void aadWidget(Widget w, String name){
this.add(w);
widgetsMap.put(name, w);
}
//When we want to delete and just have the name, we can search the key on the map.
//It is important to remove all references to the widget (panel and map)
public void removeWidget(String name){
this.remove(widgetsMap.get(name));
widgetsMap.remove(name);
}
}
I'm not sure how to ask this question, and I'm certain that there's some kind of other solution to the problem I'm having so if anyone can point me in the right direction, I'd appreciate it.
In any case, the issue I'm having is that I have a String[] list (called "projects") that I'm using to populate a combo box. I want to use the selection from the combo box to dynamically change the form fields listed in a GUI panel.
My approach, so far, isn't dynamic enough because I will have nearly 100 possible selections from the combo box when I'm done. So far, I've been testing with 3 options in the box, but scaling it up to 100 will involve a lot of code, and I think there MUST be some other solution, right? I just don't know what that solution is.
String[] projects = {"Select a project...", "Option1", "Option2", "Option3"};
String[] Option1= {"phone", "maxphv"};
String[] Option2= {"address1", "address2", "house", "predir", "street", "strtype", "postdir", "apttype", "aptnbr"
, "city", "state", "zip"};
String[] Option3= {"phone"};
ArrayList<String> fieldslist, fieldslbllist;
Ideally, I'd like to take the name of the project selected from the projects String[] combo box and reference that name as the name of another list that contains the fields I want to display in the panel.
But I gather from reading on other questions that the name of a variable is irrelevant once the code is compiled.
At this point, I have a set of code to clear the panel and dynamically select the fields, but I still have to manually code the replacement for each of the 100 options. That's not terrible, I suppose, but I think that there is probably a better way that I am unaware of.
public void resetFields() {
fieldslist.clear();
fieldslbllist.clear();
}
public void setFields() {
if (project.getSelectedIndex() == 0) {
resetFields();
}
else if (project.getSelectedIndex() == 1) {
resetFields();
for (int i = 0; i <= Option1.length; i++) {
fieldslist.add(Option1[i]);
fieldslbllist.add(Option1[i]+"lbl");
}
}
else if (project.getSelectedIndex() == 2) {
resetFields();
for (int i = 0; i <= Option2.length; i++) {
fieldslist.add(Option2[i]);
fieldslbllist.add(Option2[i]+"lbl");
}
}
//... onward to 100
The above is just a loop that resets the display on selection of a new option in the combo box and then loops through the options in the OptionX String[] list and adds the values to the fields Array.
Is this a viable way to handle dynamic UI coding? And, is there any way to set it up so I will only have to specify which fields belong to each value and then not have to code a section for each possible project.getSelectedIndex() value in setFields()?
Use CardLayout, seen here, to change the form dynamically. Given the large number of alternatives, look for a hierarchical breakdown among the choices that might allow you to use two related controls, as shown here.
I'm trying to setup a GUI to display an array of classes, but can't figure out how to add the array to the GUI. I'm fairly new to Java, so I could use all the help possible.
Book[] bk = new Book{10]
JFrame frame = new JFrame("Bookstore");
frame.setSize(600, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
JPanel panel = new JPanel();
frame.getContentPane().add(panel, BorderLayout.NORTH);
frame.getContentPane().add(panel);
frame.setVisible(true);
class Book implements Comparable<Book> {
//rest of code }
How would I display Book in the GUI?
You're question's a bit unclear, but if you want to present the names of the books in a GUI, first you need to give each Book a name, aka a string representation. Add a name attribute to Book with a getName() method.
Then create a String array containing the names of the books. You can do that by:
String names = new String[books.length];
for(int i=0; i<names.length; i++){
names[i] = books[i].getName();
}
Then you can input all the names into a JTextArea, or possibly a JComboBox if you want users to be able to choose a book.
With a JComboBox:
JComboBox combo = new JComboBox(names);
panel.add(combo);
With a JTextArea:
JTextArea textArea = new JTextArea(10,names.length);
textArea.setEditable(false);
for(int i=0; i<names.size; i++){
textArea.append("Book " + i + "#: " + names[i] + "\n");
}
panel.add(textArea);
Hope this helps.
When you need to display the attributes of a collection or array of objects of a class, you have several options available to you including:
The simplest would be to use a JTextArea, give it a monospaced font, and display the String representation of each object, with each object on one line, and using a formatted String, such as can be obtained via String.format(...), to display the contents.
Better would be to put your collection of objects into a TableModel of some sort and then display the data in a JTable. Easiest would be to use a DefaultTableModel, but this will require that you convert the attributes of each Book object into an array or Vector of Object. More flexible would be to create your own class that extends AbstractTableModel, but this will require more work on your part to create the appropriate methods of the TableModel, and making sure to fire the correct AbstractTableModel notification methods when any of these methods change the data nucleus (usually a collection of Book object) in any significant way.
If you want to display one object's attributes at time, you could populate your GUI with several JTextFields, each one corresponding to an attribute of your Book object, and then use Next and Previous JButtons to move through your collection of Books, displaying the attributes of the selected book on button press. Say when the next button is pressed, an int index variable that is used to select a Book from the collection is incremented, and the Book corresponding to that index is selected. Then all of the attributes from that selected Book are displayed in their corresponding text field.
The details will depend on which route you go.