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.
Related
i am stuck with a new problem, don't know if this works but here i have list of JCombobox as follow.
JCombobox comboBox = new JComboBox();
comboBox.addItem("UserName");
comboBox.addItem("Password");
comboBox.addItem("DLNo 20 b");
comboBox.addItem("DLNo 20 b");
i want to print my database column names which are more than 40!
when i select the Combobox it must internally print my custom item here.
Here i tried with this code but i am not satisfied with this
if(comboBox.getSelectedIndex()==0)
{
System.out.println("U_NAME");
}
if(comboBox.getSelectedIndex()==1)
{
System.out.println("P_NAME");
}
if(comboBox.getSelectedIndex()==2)
{
System.out.println("DL_NO_20_b");
}
if(comboBox.getSelectedIndex()==3)
{
System.out.println("DL_NO_20_b");
}
is there any better way to over come this, like mapping objects
You could create a class ComboBoxItem with a name- and a columnName-attribute.
Use instances of this class for the ComboBox.
In the ComboBoxItem-class, overwrite the toString()-method to return the name, so it gets displayed as wished in the ComboBox. Add a getColumnName()-method to return the columnName, so you could invoke getSelectedItem().getColumnName().
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.
I have a JPanel on which I've dynamically added quite a few JButtons. All of this is working perfectly. Later on in my program execution, I need to refer back to these buttons and pull out the button text. I'm having trouble figuring out how to refer back to them.
When I created each button, I gave it a unique name. Let's say this is the code where I created the button:
public void createButton(Container parent, String btnName) {
JButton btn = new JButton("xyz");
btn.setName(btnName);
btn.addActionListner(new ActionListner() {
//code
}
parent.add(btn);
}
In another method, I'm trying to retrieve the label on the button since it may have changed at run time. Do I need to keep an array of these buttons as they are created? Or is there a way that I can refer back to them directly?
This is what I was working on, but it's stupid. Can anyone suggest a correct approach?
public String getBtnLabel(String btnName) {
JButton btn = (JButton) btnName;
return btn.getText();
}
If the answer is that I just need to create the array and then iterate over it, that's fine. Just looking for other options.
You need to use a Map<String, JButton> so when you create your dynamic buttons you give them some sort of unqiue name:
//somewhere at the top of your class
private final Map<String, JButton> myButtonMap = new HashMap<>();
public void createButton(Container parent, String btnName) {
JButton btn = new JButton("xyz");
btn.setName(btnName);
btn.addActionListner(new ActionListner() {
//code
}
parent.add(btn);
myButtonMap.put(btnName, btn);
}
And then simply get from the map
public String getBtnLabel(String btnName) {
return myButtonMap.get(btnName).getText();
}
This will obviously throw an NPE if the button isn't defined...
Also you will need to delete from your map when you're done with it otherwise you're asking for a memory leak...
I suggest you to use a Map< String, JButton >.
At creation time you put new button into it with buttons.put( name, btn )
In event handler you use JButton btn = buttons.get( name )
Yes you need to keep references to the buttons. An array would be an option, but since arrays are awkward to use, you should prefer a List.
If you have a a reference to the JPanel containing the buttons, you could get them from it. but that is likely to be rather bothersome.
I would recommend keeping a list of your buttons or a reference to them in a map, however you could do this:
for (Component i : parent.getComponents()) {
if (i.getName().equals(btnName)) {
JButton b = (JButton) i;
// do stuff..
}
}
Using the parent component and iterating over the added components.
I created a store that saves records of person instances.
when adding the employees from CLI it works and the store increments, when using swing and CLI for debug i can see the new record but the increment is not done !
submit.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
Store recordStore;
recordStore = new Store(1);
// here add the submitting text
Employee em = new Employee("mn",'M', new Date(18,12,1991), "025", new Date(2,5,2009));
if (!Store.isFull())
{
recordStore.add(em);
recordStore.displayAll();
System.out.println("Current size of store is " + Store.getCount());
}
else
{ JOptionPane.showMessageDialog(null, "The store seems to be full, please save it, and create a new one!"); }
The store add function
public void add(Person p)
{
// person p is added to array
list[count++] = p;
}
I suspect that your problem is that you're creating a new Store instance each time the ActionListener code is run. Perhaps you want to create a Store instance once in the class and add to it in the ActionListener.
public void add(Person p)
{
// person p is added to array
list[count++] = p;
}
If above function is defined in the Store class then you are initializing a new instance
Store recordStore;
recordStore = new Store(1);
every time. So your list count will always be 1. So as Hovercraft Full Of Eels has suggested
move that outside the ActionListener class and change code accordingly.
Or else use a static count that stores the count of records of person instances that you have added.
I use JcomboBox as a suggestion box that when user type in, it check for matches and display suggestion.
Here is how I create the JComboBox:
Vector<String> popUpVector = new Vector<String>();
JComboBox jcb = new JComboBox(popUpVector);
every time Key Listener catch event, I do this
popUpVector.clear();
jcb.hidhPopUp();
for(String s : database){
popUpVector.add(s);
}
jcb.showPopUp();
It works as long as I don't select item from the dropdown.
However, once I select item from the dropdown, the dropDown will display blank afterward, I check the popUpVector, it is not empty though, I think it has something to do with the selection, so I unhook it from actionListener, it didn't helps.
Can anyone help me with this, thanks a lot!
Passing a Vector to the JComboBox constructor will according to the source indeed use that vector to back the underlying model:
public JComboBox(Vector<?> items) {
super();
setModel(new DefaultComboBoxModel(items));
init();
}
and
public DefaultComboBoxModel(Vector<?> v) {
objects = v;
if ( getSize() > 0 ) {
selectedObject = getElementAt( 0 );
}
}
Meaning that if you change the contents of the vector, you also change the contents of your model. However, making changes to the model requires to fire the correct events to inform the view about the changes. And since vector does not fire any events, the DefaultComboBoxModel has no way of knowing that the contents of the vector has been changed.
So imo the DefaultComboBoxModel constructor simply should have taken the elements from the vector and store those iso storing the vector directly.
Now to solve your problem: instead of storing your values in a Vector, use a DefaultComboBoxModel and use the available API on that model to make the changes. Using the API will make sure the model fires the correct changes. See for example the implementation of the addElement method:
public void addElement(Object anObject) {
objects.addElement(anObject);
fireIntervalAdded(this,objects.size()-1, objects.size()-1);
if ( objects.size() == 1 && selectedObject == null && anObject != null ) {
setSelectedItem( anObject );
}
}
your issue is
popUpVector.clear();
correct way to clear the Vector is only
popUpVector = new Vector<String>();
better could be to add / remove / modify the JComboBoxes Items in ComboBoxModel