Java Forum / First Aid / June 2008
how to delete a JList element
Thufir - 20 Jun 2008 23:56 GMT I don't see why I'm getting "cannot find symbol" because this JList uses a DefaultListModel, for the time being, which certainly has the missing method:
init: deps-jar: Compiling 2 source files to /home/thufir/JavaProject29/build/classes /home/thufir/bcit-comp2611-project2/src/a00720398/view/NewJFrame.java: 198: cannot find symbol symbol : method removeElementAt(int) location: interface javax.swing.ListModel guestList.getModel().removeElementAt(i); 1 error BUILD FAILED (total time: 39 seconds)
thufir@arrakis:~/bcit-comp2611-project2$ thufir@arrakis:~/bcit-comp2611-project2$ cat src/a00720398/view/ NewJFrame.java | head -n 200 | tail -n 7 private void deleteGuestActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_deleteGuestActionPerformed {//GEN-HEADEREND:event_deleteGuestActionPerformed int i =guestList.getSelectedIndex(); System.out.println("delete current guest" + i); guestList.getModel().removeElementAt(i); //guestList.getModel(). ??? }//GEN-LAST:event_deleteGuestActionPerformed thufir@arrakis:~/bcit-comp2611-project2$
what am I doing wrong?
thanks,
Thufir
Thufir - 21 Jun 2008 00:04 GMT I was looking in the wrong place. I think that:
thufir@arrakis:~/bcit-comp2611-project2$ thufir@arrakis:~/bcit-comp2611-project2$ cat src/a00720398/view/ NewJFrame.java | head -n 200 | tail -n 7 private void deleteGuestActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_deleteGuestActionPerformed {//GEN-HEADEREND:event_deleteGuestActionPerformed int i =guestList.getSelectedIndex(); System.out.println("delete current guest" + i); guestList.remove(i); }//GEN-LAST:event_deleteGuestActionPerformed
thufir@arrakis:~/bcit-comp2611-project2$
will work, except that the JList, guestList, doesn't reflect the changes. How do I test it?
thanks,
Thufir
Matt Humphrey - 21 Jun 2008 00:18 GMT >I was looking in the wrong place. I think that: > [quoted text clipped - 13 lines] > will work, except that the JList, guestList, doesn't reflect the > changes. How do I test it? JList's remove method is inherited from its superclass Container, so it really doesn't have anything to do with the list contents. Ideally, you should remove the item from the underlying JList model, which is what your prior message was attempting. The reason it didn't work is that JList.getModel () returns a ListModel, which doesn't expose the method. Of course, if you just have the one list you already have a reference to it outside the JList, so you can access it directly. If you have to go through the JList, you can cast it like
DefaultListModel l = (DefaultListModel)(guestList.getModel())
Matthew Humphrey http://www.iviz.com/
Thufir - 21 Jun 2008 02:37 GMT [...]
> JList's remove method is inherited from its superclass Container, so it > really doesn't have anything to do with the list contents. Ideally, you [quoted text clipped - 8 lines] > > Matthew Humphreyhttp://www.iviz.com/ I don't need to call paint() or anything like that once the underlying list is updated?
-Thufir
Matt Humphrey - 21 Jun 2008 03:27 GMT [...]
> > JList's remove method is inherited from its superclass Container, so it > > really doesn't have anything to do with the list contents. Ideally, you [quoted text clipped - 14 lines] > I don't need to call paint() or anything like that once the underlying > list is updated? Nope, it works for you. Give it a try. (As an aside, paint is what the EDT uses to render the GUI component--you would probably never need to call that yourself. If you need to request that the component be redrawn, use repaint. Just be aware that the painting will happen after any code in the EDT--including your request--finishes.)
Matthew Humphrey http://www.iviz.com/
Roedy Green - 21 Jun 2008 04:00 GMT On Fri, 20 Jun 2008 18:37:28 -0700 (PDT), Thufir <hawat.thufir@gmail.com> wrote, quoted or indirectly quoted someone who said :
>I don't need to call paint() or anything like that once the underlying >list is updated? see http://mindprod.com/jgloss/repaint.html
 Signature Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
Roedy Green - 21 Jun 2008 03:59 GMT On Fri, 20 Jun 2008 16:04:30 -0700 (PDT), Thufir <hawat.thufir@gmail.com> wrote, quoted or indirectly quoted someone who said :
> guestList.remove(i); You are suffering from wishful/religious thinking. You wished there were a ListModel .remove method so you just used it without checking in the JavaDoc that indeed there was such a beast.
Similarly here you wished for a method to remove possible choices from the list. remove looked like it might fit the bill, so you used it without reading the JavaDoc. You will find it has to do with removing the JList itself from its container.
See http://mindprod.com/jgloss/jlist.html for sample code on how to use JList and links to the JavaDoc both on Sun's site and on your own desktop's JDK.
 Signature
Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
Roedy Green - 21 Jun 2008 03:51 GMT On Fri, 20 Jun 2008 15:56:52 -0700 (PDT), Thufir <hawat.thufir@gmail.com> wrote, quoted or indirectly quoted someone who said :
> guestList.getModel().removeElementAt(i); JList.getModel() -> ListModel
ListModel does not have any sort of remove method.
However DefaultListModel does. If your model were a DefaultListModel then you could cast to (DefaultListModel) or simply hold onto a reference to it and use its removeElementAt method.
You could also modify the backing collection and do a new setModel if you were using some custom ListModel implemenation.
 Signature
Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
thufir - 21 Jun 2008 22:01 GMT > ListModel does not have any sort of remove method. > > However DefaultListModel does. If your model were a DefaultListModel > then you could cast to (DefaultListModel) or simply hold onto a > reference to it and use its removeElementAt method. This seems to give a NullPointerException, as below, because the backing collection is a DefaultListModel:
java.lang.NullPointerException at a00720398.view.NewJFrame.displayGuest(NewJFrame.java:458) at a00720398.view.NewJFrame.showGuest(NewJFrame.java:435) at a00720398.view.NewJFrame.showGuest(NewJFrame.java:486) at a00720398.view.NewJFrame.access$000(NewJFrame.java:13) at a00720398.view.NewJFrame$1.valueChanged(NewJFrame.java:332) at javax.swing.JList.fireSelectionValueChanged(JList.java:1765) ...
thufir@arrakis:~/bcit-comp2611-project2$ thufir@arrakis:~/bcit-comp2611-project2$ head src/a00720398/view/ NewJFrame.java -n 481 | tail -n 10 private void deleteGuestActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_deleteGuestActionPerformed {//GEN-HEADEREND:event_deleteGuestActionPerformed int i =guestList.getSelectedIndex(); BedAndBreakfast bnb = BedAndBreakfast.getInstance(); //the "database" System.out.println("delete guest \t" + i + bnb.getGuests().get(i)); ((DefaultListModel)(guestList.getModel())).removeElementAt(i); System.out.println("bnb\n" + bnb.toString()); }//GEN-LAST:event_deleteGuestActionPerformed thufir@arrakis:~/bcit-comp2611-project2$
So, I think that I'll have to change BedAndBreakfast.getGuests() not to return a DefaultListModel, which I assume is causing the NullPointerException, but rather have it return, for instance, a Vector.
yes/no?
thanks,
Thufir
thufir - 21 Jun 2008 22:23 GMT > This seems to give a NullPointerException, as below, because the backing > collection is a DefaultListModel: I got basically the same result when trying to change the backing DefaultListModel directly:
thufir@arrakis:~/bcit-comp2611-project2$ thufir@arrakis:~/bcit-comp2611-project2$ head src/a00720398/view/ NewJFrame.java -n 481 | tail -n 10 private void deleteGuestActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_deleteGuestActionPerformed {//GEN-HEADEREND:event_deleteGuestActionPerformed int i =guestList.getSelectedIndex(); BedAndBreakfast bnb = BedAndBreakfast.getInstance(); //the "database" System.out.println("delete guest \t" + i + bnb.getGuests().get(i)); //((DefaultListModel)(guestList.getModel())).removeElementAt(i); bnb.getGuests().removeElementAt(i); }//GEN-LAST:event_deleteGuestActionPerformed thufir@arrakis:~/bcit-comp2611-project2$
it runs and, apparently, works but there are still run time java.lang.NullPointerException errors.
I can change bnb.getGuests() to return a Map, but then HashMap doesn't convert nicely to an array...
I assume that the NullPointerException is because DefaultListModel doesn't nicely handle a change of index?
-Thufir
Roedy Green - 22 Jun 2008 01:08 GMT >I can change bnb.getGuests() to return a Map, but then HashMap doesn't >convert nicely to an array... See how to export a HashMap to an array at http://mindprod.com/jgloss/hashmap.html
The trick is to use values() or keySet() to get a Collection then use toArray()
 Signature
Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
Nick - 22 Jun 2008 02:34 GMT On Jun 21, 5:08 pm, Roedy Green <see_webs...@mindprod.com.invalid> wrote: [...]
> The trick is to use values() or keySet() to get a Collection then use > toArray() [...]
Right, in my GUI:
guestJList.setModel(BedAndBreakfast.getInstance().listModel); //BedAndBreakfast is the "database"
and then in BedAndBreakfast:
/*@see GUI *this method makes the DefaultListModel match the *HashMap which stores the data. *ideally, this method shouldn't be required. *I'm not quite sure why, but without it *nothing synchronizes with the JList.setModel *in the GUI*/ public void sync() { listModel.clear(); Collection<?> foos = getGuests(); for (Object obj : foos) {listModel.addElement(obj);} }
to try to "sync" up the Map with the ListModel because every example I see imbeds the data in with the JList, which is what I think I'm going to do.
Sending an Array or Vector from the "database" (BedAndBreakfast) just has no effect on syncing with the JList.
For what it's work, here's the "database":
package a00720398.data;
import java.util.*; import javax.swing.*; import a00720398.util.*;
public class BedAndBreakfast {
private static final BedAndBreakfast INSTANCE = new BedAndBreakfast();
private HashMap guests = new LinkedHashMap<Integer, Guest>(); public DefaultListModel listModel = new DefaultListModel();
private BedAndBreakfast() {sync();}
public static BedAndBreakfast getInstance() {return INSTANCE;}
/*@see GUI *this method makes the DefaultListModel match the *HashMap which stores the data. *ideally, this method shouldn't be required. *I'm not quite sure why, but without it *nothing synchronizes with the JList.setModel *in the GUI*/ public void sync() { listModel.clear(); Collection<?> foos = getGuests(); for (Object obj : foos) {listModel.addElement(obj);} }
public Collection<?> getGuests() { return guests.values(); }
public void removeGuest(int i) { System.out.println("index: " + i); guests.remove(i); sync(); }
@SuppressWarnings( "unchecked" ) public void addGuest(Guest guest) { sync(); if (guest.getID() == 0) { //if ID is default value int i = getGuests().size() + 1; guest.setID(i); //kludge to append to the "end" of the Map }
guests.put(guest.getID(), guest); //hopefully no duplicates sync(); //System.out.println("\n************\n" + getGuests()); } }
When I have the JList.setModel method convert the Map to Array it simply fails to sync :(
thanks,
Thufir
thufir - 22 Jun 2008 03:46 GMT > See how to export a HashMap to an array at > http://mindprod.com/jgloss/hashmap.html Whether it was a HashMap or anything else, I just couldn't sync it with the JList. I ended up with the following kludge:
private DefaultListModel defaultListModel = fixModel();
guestList.setModel(defaultListModel);
private DefaultListModel fixModel() { DefaultListModel dlm = new DefaultListModel(); Object[] guests = BedAndBreakfast.getInstance().getGuests().toArray (); for (Object obj : guests) { dlm.addElement(obj); } return dlm; }
Which is the only way I've ever seen it done. I know that it's possible to sync with, for example, a HashMap or Collection in the "database", BedAndBreakfast, but my attempts failed :(
-Thufir
Roedy Green - 22 Jun 2008 14:14 GMT > for (Object obj : guests) > { > dlm.addElement(obj); > } DefaultListModel, unlike similar beasts has no constructor or add method that takes mulitple entries at once.
You probably don't need the intermediate toArray. You can iterate over a Collection, or List directly.
DefaultListModel does have a remove operation.
A tidy solution might be to extend DefaultListModel to do the whole job of managing that data, add some generics, then you can avoid copying back and forth.
Another solution may be to modify your basic collection to implement ListModel by adding a few methods.
 Signature
Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
thufir - 28 Jun 2008 16:03 GMT > DefaultListModel does have a remove operation. > > A tidy solution might be to extend DefaultListModel to do the whole job > of managing that data, add some generics, then you can avoid copying > back and forth. It kinda works by extending DefaultListModel:
thufir@arrakis:~/bcit-comp2611-project2$ thufir@arrakis:~/bcit-comp2611-project2$ cat src/a00720398/data/ GuestsModel.java package a00720398.data;
import javax.swing.*; import a00720398.util.*;
@SuppressWarnings({"unchecked", "serial"}) public class GuestsModel extends DefaultListModel{
private static final GuestsModel INSTANCE = new GuestsModel();
private GuestsModel() { java.util.List<Guest> guests = FileUtil.readGuests(); System.out.println("guests \n" + guests.toString());
for (Guest guest : guests) { addElement(guest); } //addAll(0,guests); }
public static GuestsModel getInstance() { return INSTANCE; }
} thufir@arrakis:~/bcit-comp2611-project2$
and then in the view:
private void deleteGuestActionPerformed(java.awt.event.ActionEvent evt) { int i = guestsView.getSelectedIndex(); GuestsModel.getInstance().remove(i); guestsView.setModel(GuestsModel.getInstance()); //controller? }
However, I'm always having to call guestView.setModel(), and I seem to be missing a controller as per:
Controller Processes and responds to events, typically user actions, and may invoke changes on the model.
http://en.wikipedia.org/wiki/Model_view_controller
I have a seperate class, GuestsController, but what would it do here? I only see one line of deleteGuestActionPerformed to put in a controller, albeit that line is scattered throughout the view.
Maybe I could somehow put that entire method into a separate class? I could maybe do that with an inner class.
-Thufir
Roedy Green - 22 Jun 2008 00:59 GMT > ((DefaultListModel)(guestList.getModel())).removeElementAt(i); you want to find out exactly what is null before you start changing you code.
Use some more temporary variables and assert x != null: "x is null";
It could by you have no model set. It could be guestlist is null.
 Signature
Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
thufir - 30 Jun 2008 08:09 GMT > you want to find out exactly what is null before you start changing you > code. For some reason, getSelectedValue sometimes returned null:
private void showGuest(javax.swing.event.ListSelectionEvent evt) {
if (evt.getValueIsAdjusting()) { return; }
//why check for null? if (guestsView.getSelectedValue() != null) { Guest guest = (Guest) guestsView.getSelectedValue(); fName.setText(guest.getFirstName()); //and set some others } }
If evt.getValueIsAdjusting is false, then a JList element has been clicked. How can a "null" get clicked?
-Thufir
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|