Delete an item from wxListCtrl.

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
dkaip
Super wx Problem Solver
Super wx Problem Solver
Posts: 334
Joined: Wed Jan 20, 2010 1:15 pm

Delete an item from wxListCtrl.

Post by dkaip »

Hello in code bellow i am trying to delete items from wxListCtrl, but i take an error on OnSelectItem, last line.
The pos i of item is ok.
../include/wx/dynarray.h(838): assert "uiIndex < m_nCount" failed in Item().
Thank you
Jim.

Code: Select all

TextDrop::TextDrop(const wxString& title)
    : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(900, 600))
{

    wxSplitterWindow *spl1 = new wxSplitterWindow(this, -1);
    wxSplitterWindow *spl2 = new wxSplitterWindow(spl1, -1);
    m_gdir = new wxGenericDirCtrl(spl1, -1, wxT("/home/"),wxPoint(-1, -1), wxSize(50, 50), wxDIRCTRL_DIR_ONLY);

    m_lc1 = new wxListCtrl(spl2, -1, wxPoint(50, 50),wxSize(50, 50), wxLC_LIST);
    m_lc2 = new wxListCtrl(spl2, -1, wxPoint(50, 50),wxSize(50, 50), wxLC_LIST);

    MyTextDropTarget *mdt = new MyTextDropTarget(m_lc2);
    m_lc2->SetDropTarget(mdt);

    Connect(m_lc1->GetId(), wxEVT_COMMAND_LIST_BEGIN_DRAG,wxListEventHandler(TextDrop::OnDragInit));

    wxTreeCtrl *tree = m_gdir->GetTreeCtrl();

    spl2->SplitHorizontally(m_lc1, m_lc2);
    spl1->SplitVertically(m_gdir, spl2);

    Connect(tree->GetId(), wxEVT_COMMAND_TREE_SEL_CHANGED,wxCommandEventHandler(TextDrop::OnSelect));
    Connect(m_lc2->GetId(), wxEVT_COMMAND_LIST_ITEM_SELECTED,wxListEventHandler(TextDrop::OnSelectItem));

    Center();
}
MyTextDropTarget::MyTextDropTarget(wxListCtrl *owner)
{
    m_owner = owner;
}

bool MyTextDropTarget::OnDropText(wxCoord x, wxCoord y,const wxString& data)
{
    m_owner->InsertItem(0, data);
    return true;
}

void TextDrop::OnSelectItem(wxListEvent& event)
{
    wxListItem it=event.GetItem();
    long i=it.GetId();
//    m_lc2->DeleteItem(i);
    m_lc2->DeleteAllItems();
}
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Delete an item from wxListCtrl.

Post by doublemax »

I assume the line that causes the problem is:

Code: Select all

m_lc2->DeleteItem(i);
and not the other one?

The assert message is clear: The item index is bigger too big and exceeds last item in the control. Check the values of "i" and "m_lc2->GetItemCount".
Use the source, Luke!
dkaip
Super wx Problem Solver
Super wx Problem Solver
Posts: 334
Joined: Wed Jan 20, 2010 1:15 pm

Re: Delete an item from wxListCtrl.

Post by dkaip »

Yes this is line with problem.
I assume the line that causes the problem is:
m_lc2->DeleteItem(i);
Supposse m_lc2 has 2 objects, and click to first i take i=0 and j=2.
But i<j and proplem is the same.
Is problem of library? I use wxWidgets3.0.3 stable.
Even using DeleteAllItems () i have the same problem, so must be in library?
Thank you
Jim

Code: Select all

    wxListItem it=event.GetItem();
    long i=it.GetId();
    int j=m_lc2->GetItemCount();
    m_lc2->DeleteItem(i);
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Delete an item from wxListCtrl.

Post by doublemax »

Even using DeleteAllItems () i have the same problem, so must be in library?
Very unlikely, there must be something elso going on.

Please try to create a minimal, compilable sample that shows the problem.
Use the source, Luke!
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: Delete an item from wxListCtrl.

Post by PB »

Using the simple code below it basically (did not test how multiple selection works) seems to work as expected( git master, MSW)

Code: Select all

#include <wx/wx.h>
#include <wx/listctrl.h>

class MyFrame : public wxFrame
{
public:
    MyFrame() : wxFrame(NULL, wxID_ANY, "Test", wxDefaultPosition, wxSize(600, 400))
    {                               
        wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);        

        m_listCtrl = new wxListCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_LIST);        
        for ( int i = 0; i < 20; ++i )
            m_listCtrl->InsertItem(m_listCtrl->GetItemCount(), wxString::Format("Item %d", i));            
        m_listCtrl->Bind(wxEVT_COMMAND_LIST_ITEM_SELECTED, &MyFrame::OnItemSelected, this);
        mainSizer->Add(m_listCtrl, wxSizerFlags().Expand().Proportion(3).Border(wxALL, 10));

         wxTextCtrl* logCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString, 
            wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH2);        
        mainSizer->Add(logCtrl, wxSizerFlags().Expand().Proportion(1).Border(wxALL, 10));
        wxLog::SetActiveTarget(new wxLogTextCtrl(logCtrl));      
                            
        SetSizer(mainSizer);         
    }	
private:
    wxListCtrl* m_listCtrl;

    void OnItemSelected(wxListEvent& evt)
    {        
        const long itemId = evt.GetItem().GetId();        

        wxASSERT(itemId == evt.GetIndex());
        
        wxLogMessage("OnItemSelected(): itemId = %ld, item count = %ld", 
            itemId, m_listCtrl->GetItemCount());

        m_listCtrl->DeleteItem(itemId);
    }
};

class MyApp : public wxApp
{
public:	
	bool OnInit()
	{
        (new MyFrame)->Show();
        return true;
	}
}; wxIMPLEMENT_APP(MyApp);
dkaip
Super wx Problem Solver
Super wx Problem Solver
Posts: 334
Joined: Wed Jan 20, 2010 1:15 pm

Re: Delete an item from wxListCtrl.

Post by dkaip »

Hello.
I upload the code, is from zetcode example.
Thank you
Jim
Attachments
drag and drop.zip
(1.73 KiB) Downloaded 86 times
dkaip
Super wx Problem Solver
Super wx Problem Solver
Posts: 334
Joined: Wed Jan 20, 2010 1:15 pm

Re: Delete an item from wxListCtrl.

Post by dkaip »

For PB code i take error when pick an item...
Is library's bug?
/usr/include/wx-3.0/wx/strvararg.h(456): assert "(argtype & (wxFormatStringSpecifier<T>::value)) == argtype" failed in wxArgNormalizer(): format specifier doesn't match argument type
But when disable code

Code: Select all

//        wxLogMessage("OnItemSelected(): itemId = %ld, item count = %ld",
//            itemId, m_listCtrl->GetItemCount());
on item click item delete. But when click on last item i take error ...
../include/wx/dynarray.h(838): assert "uiIndex < m_nCount" failed in Item().
No drag and drop operation happens.
Thank you
Jim
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Delete an item from wxListCtrl.

Post by doublemax »

I upload the code, is from zetcode example.
Under Windows i don't see any crash with your code. I can't test under Linux.
Use the source, Luke!
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: Delete an item from wxListCtrl.

Post by PB »

dkaip wrote:For PB code i take error when pick an item...
Is library's bug?
/usr/include/wx-3.0/wx/strvararg.h(456): assert "(argtype & (wxFormatStringSpecifier<T>::value)) == argtype" failed in wxArgNormalizer(): format specifier doesn't match argument type
But when disable code

Code: Select all

//        wxLogMessage("OnItemSelected(): itemId = %ld, item count = %ld",
//            itemId, m_listCtrl->GetItemCount());
This may be because GetItemCount() returns int and therefore the second printf specifier should be "%d" and not "%ld" (on my platform there is not difference between int and long). But as you said, this has no relation to the issue in question...
dkaip
Super wx Problem Solver
Super wx Problem Solver
Posts: 334
Joined: Wed Jan 20, 2010 1:15 pm

Re: Delete an item from wxListCtrl.

Post by dkaip »

In Linux wxWidgets lib must have problem.
It must works on both OS.
Thank you
Jim.
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: Delete an item from wxListCtrl.

Post by PB »

While it does not seem very likely, perhaps deleting the item in the OnSelect event handler may be an issue. Try doing it with CallAfter instead, e.g. like this

Code: Select all

#include <wx/wx.h>
#include <wx/listctrl.h>

class MyFrame : public wxFrame
{
public:
    MyFrame() : wxFrame(NULL, wxID_ANY, "Test", wxDefaultPosition, wxSize(600, 400))
    {                               
        wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);       

        m_listCtrl = new wxListCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_LIST);       
        for ( int i = 0; i < 5; ++i )
            m_listCtrl->InsertItem(m_listCtrl->GetItemCount(), wxString::Format("Item %d", i));           
        m_listCtrl->Bind(wxEVT_COMMAND_LIST_ITEM_SELECTED, &MyFrame::OnItemSelected, this);
        mainSizer->Add(m_listCtrl, wxSizerFlags().Expand().Proportion(3).Border(wxALL, 10));

         wxTextCtrl* logCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
            wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH2);       
        mainSizer->Add(logCtrl, wxSizerFlags().Expand().Proportion(1).Border(wxALL, 10));
        wxLog::SetActiveTarget(new wxLogTextCtrl(logCtrl));     
                           
        SetSizer(mainSizer);         
    }   
private:
    wxListCtrl* m_listCtrl;

    void DeleteListCtrlItem(long item)
    {
        wxLogMessage("DeleteListCtrlItem(): item = %ld, item count = %d", item, m_listCtrl->GetItemCount());
        m_listCtrl->DeleteItem(item);
    }

    void OnItemSelected(wxListEvent& evt)
    {       
        const long itemId = evt.GetItem().GetId();       

        wxASSERT(itemId == evt.GetIndex());
       
        wxLogMessage("OnItemSelected(): itemId = %ld, item count = %d", itemId, m_listCtrl->GetItemCount());
        CallAfter(&MyFrame::DeleteListCtrlItem, itemId);
    }
};

class MyApp : public wxApp
{
public:   
   bool OnInit()
   {
        (new MyFrame)->Show();
        return true;
   }
}; wxIMPLEMENT_APP(MyApp);
Post Reply