2

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

MaxVK
  • 327
  • 4
  • 14
  • I know, this is a stupid question, BUT, it sounds like the selected item does not exist (or can not equated to `equal`) a value in the model...go figure how that would work :P – MadProgrammer Jul 29 '12 at 10:45
  • Can you do a couple more things. Can you do `CharListModel.contains(CharList.getSelectedItem())` and/or `CharListModel.indexOf(CharList.getSelectedItem())` and see what they return please – MadProgrammer Jul 29 '12 at 10:47
  • 3
    For better help sooner, post an [SSCCE](http://sscce.org/). – Andrew Thompson Jul 29 '12 at 10:53
  • @MadProgrammer - I get a method not found on getSelectedItem() in both instances. – MaxVK Jul 29 '12 at 11:26
  • @AndrewThompson. Sorry Andrew, Ill try to extant something useful from the program - I have just been posting copy/paste code from it in the hope that something obvious was being missed/ – MaxVK Jul 29 '12 at 11:27
  • 1
    Please learn java naming conventions and stick to them. – kleopatra Jul 29 '12 at 11:40
  • @AndrewThompson. My apologies for taking so long, but in producing a small version of the program everything seems to work fine (naturally!) so I am trying to work out the problem in my main program. – MaxVK Jul 29 '12 at 16:57
  • And you are certain you are adding and/or removing the elements on the Event Dispatch Thread ? – Robin Jul 29 '12 at 17:00
  • @Robin - Sorry, don't fully understand what you mean. The removal is started in the ActionPerformed event of a button. Previously in other button events items can be added, and in my stripped down sample everything works precisely as it should, including loading the file and adding extra items - I now need to work out what is wrong with the main program, which is unfortunately quite large! – MaxVK Jul 29 '12 at 17:17
  • Swing components should be accessed/modified on the EDT, and cannot handle multi-threaded access. Such an `ArrayIndexOutOfBoundsException` might occur if you add/remove on different `Thread`s. The removal/adding sounds good as the button press happens on the EDT so probably not the cause in this case – Robin Jul 29 '12 at 17:22
  • @MaxVk sorry, t should ave been getSelectedValue, my bad – MadProgrammer Jul 29 '12 at 19:07
  • @MadProgrammer - lol! Glad its not only me that does that! Your question: `contains` returns true, and `indexOf` returns the correct index. I can also get the string being held at the selected index, but the moment I try to remove the element I get the same error over and over - this doesn't happen in the little test app that I tried to put together, but I cannot work out why it happens in my main app. – MaxVK Jul 30 '12 at 08:05

4 Answers4

3

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);
        }
    }
}));
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • trashgod, thanks, but I have already tried this - it works in the test app, but not in the main app and index has never == -1 until the moment I try `remove` (or an alternative). – MaxVK Jul 30 '12 at 08:08
  • Anything helpful in the stacktrace from `ArrayIndexOutOfBoundsException`? – trashgod Jul 30 '12 at 15:17
  • I have to be honest, I have no idea! There is a lot of it (which is why I have not posted it here), but the information at the very start tells me that it is the out of bounds exception. – MaxVK Jul 30 '12 at 15:22
  • One approach is to debug a similar, intentional error in the sscce as an example. See also [*An Introduction to Java Stack Traces*](http://java.sun.com/developer/technicalArticles/Programming/Stacktrace/). – trashgod Jul 30 '12 at 15:49
  • Thanks trashgod, I might find myself using that link a fair bit – MaxVK Jul 30 '12 at 16:33
2

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.

bshtein
  • 31
  • 1
  • Worked like a charm. Turns out I the error is actually called from valueChanged, as shown differently from the stack trace. – Richard Yan Sep 28 '17 at 03:24
0

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.

Noufal
  • 17
  • 1
  • 4
0

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..
} 
Orel Eraki
  • 11,940
  • 3
  • 28
  • 36
Martin
  • 68
  • 8