Updating/recreating a JList - java

This is my first post here, and I am very green with Java. This is something I'm trying to make to improve my java knowledge.
I have a button, which when clicked produces a shuffled card deck as a Jlist.
When pressed again, I would very much like it to refresh the JList, or recreate it somehow. Instead, it simply
creates a new list, so I now have 2 JLists.
button1.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
cards.choseCards(); //Creates an ArrayList with the suffled cards
JList<String> displayList = new JList<>(cards.deck.toArray(new String[0]));
frame.add(displayList);
frame.pack();
cards.cleanUpDeck(); //Removes all the cards from the ArrayList
}
});

The key here is that Swing uses a model-view type of structure similar to model-view-controller (but with differences) where the model holds the data that the view (the component) displays.
What you are doing is creating an entirely new JList, but what you want to do is to update the model of the existing and displayed JList, either that or create a new model for this same existing JList. JLists use a ListModel for their mode, often implemented as a DefaultListModel object, and so you will want to update or replace this model such as by creating a new DefaultListModel object and then inserting it into the existing JList by calling its setModel(ListModel model) method.
For example your code could look something like this (made with lots of guesses since we don't know what your real code looks like):
button1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// create new model for the JList
DefaultListModel<String> listModel = new DefaultListModel<>();
cards.choseCards(); //Creates an ArrayList with the suffled cards
// add the cards to the model. I have no idea what your deck field looks like
// so this is a wild guess.
for (Card card : cards.deck) {
listModel.addElement(card.toString()); // do you override toString() for Card? Hope so
}
// Guessing that your JList is in a field called displayList.
displayList.setModel(listModel); // pass the model in
cards.cleanUpDeck(); //Removes all the cards from the ArrayList
}
});

Related

JList - selecting option

how do i go do this, based on input in textfield, you get some results inside jlist, after you select option in jlist you then get an action, code examples would be appreciated... this is what i got so far:
final DefaultListModel<String> locations = new DefaultListModel<String>();
getTextFieldSearch().addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
for(int i=0;i<10;++i) {
locations.add(i, "blah");
}
}
});
JList<String> list_racentRaces = new JList<String>(locations);
Start by taking a look at How to Use Lists, which has lots of awesome code examples.
The basic idea would be to...
When your actionPerformed method is triggered, create a new DefaultListModel, assuming you don't have your own implementation, fill it with all the new items you need and apply it to the instance of list_racentRaces
If you want to maintain what was previously in the list, you should consider starting with a DefaultListModel and simply add the new items to it as you need to...
Then, attach a ListSelectionListener to list_racentRaces and when the valueChanged event is triggered, find the selected item(s) and do what ever you need to based on these result(s)
You can find more details and examples through How to Write a List Selection Listener

how to retrieve item ID from JList

I have a JList, where it displays names according to the DB. Associated with these names are IDs. for eg., foodId = 1, foodName = Chinese.
If i click on an item on the JList, i need to capture the foodID associated with the clicked foodName. i know a variable is needed.
when i have that value, I can pass that value into another method to retrieve the relevant food items associated with that foodId. Assume that getters & setters are done.
I have only the following, & am stuck. Please advise thank you.
list_1.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent evt) {
//alter text of Label acc to clicked item # JList
JList list = (JList)evt.getSource();
System.out.println (list.getSelectedValue());
//store int value of item clicked # JList
int temp = 0;
temp = ???????????
//populate JPanel
Food food = new Food();
JPanel panel = new JPanel();
panel.setBounds(153, 74, 281, 269);
panel.add(food.populateWithButtons());
contentPane.add(panel);
}
});
list_1.setBorder(new LineBorder(new Color(0, 0, 0), 0));
//populate JList
list_1.setModel(food.populateJList());
public ListModel populateJList()
{
DefaultListModel model = new DefaultListModel();
ResultSet rs = null;
DataAccessObject db = new DataAccessObject();
db.setUp("customer");
String dbQuery = "SELECT store_Owner_Id, food_Category FROM store_owner";
rs = db.readRequest(dbQuery);
try
{
while (rs.next())
{
food_Category = rs.getString("food_Category");
store_Owner_Id = rs.getInt("store_Owner_Id");
model.addElement(food_Category);
System.out.println (store_Owner_Id); //test DB conn & print retrieved items
System.out.println (food_Category);
}
}
catch (Exception e)
{
e.printStackTrace();
}
db.terminate();
return model;
}
Suggestions:
Don't populate the JList with Strings but rather ...
If you populate your JList with objects that contain both the name and the ID, then you're doing well.
You will likely want to give your JList a cell renderer that helps it to show the information from the object that you want the JList to display.
Then getting the ID is simply a matter of getting the selected item from the JList inside whatever listener you're using, casting it to the object type that in fact is, and then calling the getter method, such as getId(), assuming that objects of this type have this method, and then use your ID.
Note though that this tells us nothing useful:
list_1.setModel(food.populateJList());
If my suggestions don't help you answer your question, then please provide more useful information and code, information that will help us to fully understand your problem.
Edit 2
Your latest code shows that you're doing what I recommended that you not do:
while (rs.next())
{
food_Category = rs.getString("food_Category");
store_Owner_Id = rs.getInt("store_Owner_Id");
model.addElement(food_Category); // ****** here
System.out.println (store_Owner_Id);
System.out.println (food_Category);
}
You're adding Strings to your DefaultListModel, and by doing this you lose all the other information that the database gave you.
Again do not add Strings to this model. Create a class that has two or more fields, one for the category String, and one for the owner ID, that has getters, setters, and a constructor that allows you to pass this information into objects of the class, create objects of this class in your while loop above, and add these to the JList model. Then give your JList a custom renderer which is better than giving the custom object a toString() method for this purpose.
Create a custom class, say called FoodInfo
Declare the DefaultListModel as one that accepts objects of this type, DefaultListModel<FoodInfo>
Then add objects of this type to the model:
e.g.,
DefaultListModel<FoodInfo> model = new DefaultListModel<FoodInfo>();
// ... other code to get database info
while (rs.next()) {
String foodCat = rs.getString("food_Category");
int id = rs.getInt("store_Owner_Id");
FoodInfo foodInfo = new FoodInfo(foodCat, id);
model.addElement(foodInfo);
}
Edit 3
As has been noted in comment by #dic19, don't use a MouseListener on the JList but rather use a ListSelectionListener as described in the JList Tutorial.
See Combo Box With Hidden Data. It will show you how to use a custom object without the need for a custom renderer. I know the title is "Combo Box" but the concept is identical for a JList.
When you use a custom renderer you break the default functionality of JList since you will no longer be able to select items using the keyboard. A properly designed GUI should allow the use to use the mouse or keyboard to select an item.

Java: Iterate JMenuItem from ArrayList with HashMaps

I have a JFrame with a menubar, in which i'd like some dynamic menus, as in, depending on the size of the ArrayList with HashLists. The problem here is that i then got a dynamic amount of JMenuItems, so i need a way to get as much variables as HashLists. In this case i made the name of the variable static, but obviously that's not working on the ActionListener, since all MenuItems will have the same ActionListener.
I'm wondering how to solve this, and how to get a menu with a dynamic amount of menuitems which all have unique actionlisteners.
private ArrayList<HashMap> menuLijst;
.
for (HashMap h : menuLijst) {
String vraag = (String) h.get("vraag");
JMenuItem qMenu = new JMenuItem(vraag);
informatie.add(qMenu);
qMenu.addActionListener(this);
}
Thanks in advance.
Depending on what you want to do in your ActionListener, you can either use this, as you do right now and in the actionPerformed you can then use ((JMenutItem)event.getSource()) to see which menu item has been clicked. Alternatively, you could register as many ActionListeners as there are menus, like this:
for (final HashMap h : menuLijst) {
final String vraag = (String) h.get("vraag");
final JMenuItem qMenu = new JMenuItem(vraag);
informatie.add(qMenu);
qMenu.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
// here event.getSource() is the same as qMenu
System.out.println("Menu "+qMenu+" with label "+vraag+" has been pressed");
System.out.println("HashMap is "+h);
}
});
}
But to me (and also seeing your previous questions), it seems that you are abusing the usage of HashMap instead of using appropriate new objects. I don't know what else is in your HashMap, let's say that you have 3 keys: "vraag", "answer", "grade", you could create the following class:
public class MyClass {
private String vraag;
private String answer;
private int grade;
// And getters and setters here.
}
And have a List<MyClass> instead of List<HashMap>.
I don't see why you want to use a HashMap for your Strings. If you save an ArrayList of Strings, and loop over them to add them all to the menu, you can add actionListeners to all of them, just as you are doing now.
In your ActionListener, check which button is clicked by looping through the ArrayList, and comparing to the name of the clicked button.

Java - Updating JList after changing an object

I have a JList which uses a DefaultListModel.
I then add values to the model which then appear in the JList. I have created a MouseListener which (when double clicked) allows the user to edit the current user number of that person they have selected.
I have checked that the actual object of that record is being changed, and it is. The only issue I'm having is getting the actual Jlist to update to show the new values of that object.
Snippets of the current code I have are:
Creating the JList and DefaultTableModel:
m = new DefaultListModel();
m.addListDataListener(this);
jl = new JList(m);
jl.addMouseListener(this);
Updating the object:
String sEditedNumber = JOptionPane.showInputDialog(this, "Edit number for " + name, number);
if (sEditedNumber != null) {
directory.update (name, sEditedNumber);
}
And (when jl is the JList and m is the DefaultTableModel):
public void contentsChanged(ListDataEvent arg0) {
jl.setModel(m);
}
Instead of setModel(), update your existing model using one of the DefaultListModel methods such as setElementAt(), which will fireContentsChanged() for you.
You need to call fireContentsChanged() on the ListModel.
You need to call DefaultListModel.fireContentsChanged(). But since this method is protected (I really wonder why), you can't do that directly. Instead, make a small subclass:
class MinoListModel<T> extends DefaultListModel<T>
{
public void update(int index)
{
fireContentsChanged(this, index, index);
}
}
Use it as your list model:
m = new MinoListModel<>();
jl = new JList(m);
After updating a user number, update the corresponding entry: m.update(theIndex);
Alternatively, if you don't want a subclass, you can just replace the JList element after the user number changed: m.setElementAt(theSameElement, theIndex);. Though this is somewhat cumbersome and having a subclass seems the cleaner approach.

Array trouble in java

Hello
I'm making a program that tracks the number of users that are logged on by entering names through textfield0. I hit a road block being new to java I still don't understand some things I was wondering how one would add names to the array User in real time and have the array be count it show it in textfield1.
Thank you in advance.
public class UserTracking {
public static void main(String[] args){
final Kong f = new Kong();
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(200,110);
f.setVisible(true);
}
}
class Kong extends JFrame implements ActionListener
{
JTextField textfield0 = new JTextField();
JTextField textfield1 = new JTextField();
JLabel label0 = new JLabel("User");
JLabel label1 = new JLabel("Number of Users:");
JButton btnon = new JButton("Log on");
JButton btnoff = new JButton("Log off");
String User[] ={};
public Kong()
{
super("Shazam");
JPanel panel1 = new JPanel(new BorderLayout());
panel1.add(textfield0,BorderLayout.CENTER);
panel1.add(label0,BorderLayout.WEST);
JPanel panel2 = new JPanel(new BorderLayout(10,10));
panel2.add(btnon,BorderLayout.WEST);
panel2.add(btnoff,BorderLayout.EAST);
JPanel panel3 = new JPanel(new BorderLayout());
panel3.add(textfield1,BorderLayout.CENTER);
panel3.add(label1,BorderLayout.WEST);
JPanel frame = new JPanel(new BorderLayout(5,5));
frame.add(panel1,BorderLayout.NORTH);
frame.add(panel2,BorderLayout.EAST);
frame.add(panel3,BorderLayout.SOUTH);
setContentPane(frame);
}
public void actionPerformed(ActionEvent e)
{
}
}
If you've had experience with C++, think of Java arrays as C++ arrays in that once their size is defined, it stays that way. If you wish to increase the capacity, you need to recreate the array and add the contents of the old array inside. Essentially this is what vector did.
In Java if you want an expandable array, you essentially want a List object. I would strongly encourage you to use an ArrayList which is essentially the equivalent of vector in Java, allowing you to add as many objects as you want without worrying about its capacity.
If you ever need an array, you can convert it using the toArray() method (though in my experience, ArrayList does everything you'd require).
The size of an array in java can't be changed after the first initialization.
If you want a dynamic sized data container, you can use any implementation of the List interface. For example ArrayList :
ArrayList<String> user = new ArrayList<String>();
And to add each user to the ArrayList :
user.add(username);
Use an ArrayList.
What you need is not an array, but a more flexible datatype (that is able to "grow" in size) like some List implementation: ArrayList is actually backed by an array, but you don't need to manage (re)allocation yourself.
Instead of taking String array you can take ArrayList it would be easier. Something like this
ArrayList<String> user = new ArrayList<String>();
On some action like button or text change event write this
user.add(textField1.getText());
The actionPerformed method should
add a string into the User array (which should be named users)
ask the array its new length
change the value in the count textfield (textfield1, which really has a bad name)
The problem is that Java arrays have a fixed length. They can't grow. That'w why java.util.ArrayList exists : it's a class that behaves like a dynamic-length array. Read its javadoc to know how to use it.
You are also missing linking buttons to ActionListener. Once that is done, you could use ArrayList to add users to the list as they login and remove users from list as they logoff.
private ArrayList<String> loggedOnUsers = new ArrayList<String>();
and
void actionPerformed(event)
{
if(it's logOn button action)
{
add user to loggedOnUsers list
}
else
{
remove user from loggedOnUsers list
}
}

Categories

Resources