MaxVK
MaxVK

Reputation: 327

Error removing element from JList with DefaultListModel

I have a standard JList that will be changed while the program is running. In order to make life easier I have created a DefaultListModel and assigned it to the JList:

JList CharList = new JList();
DefaultListModel CharListModel = new DefaultListModel();

CharList.setModel(CharListModel);

I am able to load a file into the list, and later I can add items to the list like this:

File ChFile = new File (CharListFile);
FileReader freeder = new FileReader (ChFile);
BufferedReader breeder = new BufferedReader(freeder);
String line;
while((line=breeder.readLine())!=null)
{
int pos = CharList.getModel().getSize();
CharListModel.add(pos, line);
}
...
...
//and to add items..
int pos = CharList.getModel().getSize();
CharListModel.add(pos, NewCharName);

However, I need to be able to remove items from the list, and this is giving me some considerable trouble!

I have tried the most obvious way (Yes an item is selected, and I have already retrieved both the index and the string at that index):

CharListModel.removeElement(CharList.getSelectedValue());

However, this gives me a 'java.lang.ArrayIndexOutOfBoundsException: -1' error.

I have tried all of the permutations that you can see in the code below (Some are commented out but you get the idea):

DefaultListModel model = (DefaultListModel) CharList.getModel();//CharListModel;
int selectedIndex = CharList.getSelectedIndex();
if (selectedIndex != -1) {
    //model.remove(selectedIndex);
    //model.removeElement(CharList.getSelectedValue());
    //model.removeElementAt(selectedIndex);
}

as well as a few other permutations as well:

CharListModel.removeElementAt(CharList.getSelectedIndex());
//or
CharListModel.remove(CharList.getSelectedIndex());
//or
CharList.remove(SelItemIndex);

In each case I get the same 'ArrayIndexOutOfBoundsException' error, even though the selected index is previously found with no trouble. And yes, I know I just said 'previously' so something could have changed things, but here is the code that runs directly before I try to remove the element:

int SelItemIndex = CharList.getSelectedIndex();
if(SelItemIndex == -1)
{
    JOptionPane.showMessageDialog(null, "You have to select something!");
    return;
}
String SelItem = CharList.getModel().getElementAt(SelItemIndex).toString();
//Create warning
final JComponent[] inputs = new JComponent[]
{
    new JLabel("<html>Bla Bla " + SelItem + " Are you sure?</html>")
};
int n = JOptionPane.showConfirmDialog( null, inputs,"Deletion Confirmation Warning", JOptionPane.YES_NO_OPTION);
if( n == 1)
{
    //Do not delete
    return;
}

That is all there is before trying to remove the selected element.

For the life of me I don't know why this is not working! Am I missing something really silly here?

A confusing update

In the ActionPerformed event of a JButton I have used this code - The comments in the code explain why this is so confusing!:

DefaultListModel CharListModel = (DefaultListModel)CharList.getModel();
if( CharListModel.contains(CharList.getSelectedValue()) == true)
{
    //Selected item is found
    int selItemIndex = CharListModel.indexOf(CharList.getSelectedValue());
    if(selItemIndex != -1)
    {
        //Selected item index is NOT -1 and is correct
        CharListModel.remove(selItemIndex);
        //Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1
    }
    else
    {
        //NEVER reached
        JOptionPane.showMessageDialog(null, "OUCH!");
    }
}

As you can see, the index of the selected item is correct right up to the point of removing it, whereupon I once again get the out of bounds exception. I also tried this in the same place but with the same results:

CharListModel.removeElement(CharList.getSelectedValue());

Even more confusion

In an attempt to work out what is going on I have created a new DefaultListModel, enumerated the old one, and put each name into the new model, except the one that I want to remove (Remember I can get the index, the object and the text, I just cant delete it).

This has worked and I now have a DefaultListModel with the correct items in it, however, the moment that I try to CharList.setModel(NewModel); I once again get the out of bounds exception.

This has got me pulling out hair! Can anyone offer any ideas to try?

A Resolution of sorts

Not really a resolution at all, but to work around this maddening problem I am using the method laid out above, where I create a copy of the list model, minus the item that I want to delete and then simply catch the exception when using setModel, since the updated list model is added to the list just fine, and subsequent actions such as adding items etc. work okay, right up until I try to delete an item again anyway!

Thanks if you tried to help - and if you have any ideas about how to hunt down this problem, by all means post away!

regards

Max

Upvotes: 2

Views: 4280

Answers (4)

Martin
Martin

Reputation: 68

I have the same problem, i fix this doing that:

Button Action

int index = mylist.getSelectedIndex();
MyObject = (MyObject) mylist.getSelectedValue();
int Size = mylistmodel.getSize(); 
if (index >= 0 && MyObject != null && Size > 0) {
    modeloLista.removeElementAt(indice);
}

And.

listValueChanged

if (list.getSelectedValue() != null) {
    your code..
} 

Upvotes: 0

bshtein
bshtein

Reputation: 31

I had a similar problem. It turned out the error stemmed not from removing the element, but rather displaying the list. When implementing the

public void valueChanged(ListSelectionEvent e)

method, which updates the list on the screen, make sure to check if the model is null before you set the values. This is what caused the exceptions in my case.

Creating a list, removing from there, and then updating the model with the list is also a usable workaround.

Upvotes: 2

Noufal
Noufal

Reputation: 17

I have faced the same issue. It seems when the item is removed from the model, it gets removed from the array as well. Hence is messes up the array index.

As a work around, I moved the array contents into a List and remove the List contents from the model. Now it works fine for me.

Upvotes: 0

trashgod
trashgod

Reputation: 205785

For reference, I added the code below to this example. If it's not helpful, it may be a useful sscce for updating your question.

panel.add(new JButton(new AbstractAction("Remove") {

    @Override
    public void actionPerformed(ActionEvent e) {
        int index = list.getSelectedIndex();
        if (index != -1) {
            model.remove(index);
        }
    }
}));

Upvotes: 3

Related Questions