Qt-interest Archive, March 2007
QListBox and multiselection
Message 1 in thread
Hello,
I'm using a qlistbox widget (qt3.3.4) with multiselection enabled.
I'm using following code to remove selected items:
[code]
...
idx = 0;
item = listbox->firstItem();
while ( item )
{
if ( item->isSelected() )
{
// do something with this item
listbox->removeItem( idx );
}
idx++;
item = item->next();
}
...
[/code]
The result is, that the last highlighted item is not removed ( if they
are continous
selected ).
Another problem is, that if I select accidentaly more than those I
wanted, I move
the mouse back with left button pressed but the highlighted color
doesn't change.
Is this a bug with qlistbox?
Wolfgang
--
[ signature omitted ]
Message 2 in thread
Wolfgang Leideck wrote:
> I'm using a qlistbox widget (qt3.3.4) with multiselection enabled.
> I'm using following code to remove selected items:
>
> [code]
> ...
> idx = 0;
> item = listbox->firstItem();
> while ( item )
> {
> if ( item->isSelected() )
> {
> // do something with this item
> listbox->removeItem( idx );
> }
> idx++;
> item = item->next();
> }
> ...
> [/code]
>
> The result is, that the last highlighted item is not removed ( if they
> are continousselected ).
I have no Qt 3 installed anymore to actually check this, but
I wouldn't be surprised if QListBox::removeItem invalidated iterators
to the list, at least those 'pointing' to the removed item.
So the save way to remove itms should be to set up a sorted list of
indices to be removed and then remove them iterating through the list
in decreasing order.
Andre'
--
[ signature omitted ]
Message 3 in thread
Well, I was falling in this problem too.
My solution is like that ( it's similiar to yours Tom):
[code]
QMap<int,int> itemIdx;
// get the list of selected items
QListBoxItem* item = listbox->firstItem();
int idx = 0;
while ( item )
{
if ( item->isSelected() )
itemIdx[idx++] = tabDefList->index( item );
item = item->next();
}
// remove the items in reverse order
idx--;
while ( idx >= 0 )
{
listbox->removeItem( itemIdx[idx--] );
}
This works for me.
Thanks for help
Wolfgang
2007/3/29, Tom Panning <lurchvt@xxxxxxxxx>:
> I ran your code, and in my tests it removes every other item. Part of your
> problem is that you're trying to maintain two different "pointers" to the
> same object; you assume that idx and item both refer to the same list item,
> but they could easily get out of sync. Secondly, as Wolfgang wrote, when
> you're removing elements from a list, it's best to traverse the list
> backwards. The reason is: lets say you decide to delete element 2, then what
> was element 3 becomes element 2, but if you increment your index, you will
> move on to the new element 3 (which used to be element 4), and so you can
> skip over elements quite easily. If you go through the list backwards, then
> removing an element will not affect the indexes that you haven't seen yet.
> Here is my code that seems to work properly:
>
> for (int idx=listbox->count()-1; idx >= 0; idx--) {
> if (listbox->item(idx)->isSelected()) {
> listbox->removeItem(idx);
> }
> }
>
> Hope that helps,
> Tom
--
[ signature omitted ]