Page 1 of 1
Delete an item from wxListCtrl.
Posted: Sat Sep 15, 2018 1:15 pm
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();
}
Re: Delete an item from wxListCtrl.
Posted: Sat Sep 15, 2018 5:56 pm
by doublemax
I assume the line that causes the problem is:
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".
Re: Delete an item from wxListCtrl.
Posted: Sun Sep 16, 2018 4:31 am
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);
Re: Delete an item from wxListCtrl.
Posted: Sun Sep 16, 2018 8:10 am
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.
Re: Delete an item from wxListCtrl.
Posted: Sun Sep 16, 2018 10:34 am
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);
Re: Delete an item from wxListCtrl.
Posted: Sun Sep 16, 2018 11:21 am
by dkaip
Hello.
I upload the code, is from zetcode example.
Thank you
Jim
Re: Delete an item from wxListCtrl.
Posted: Sun Sep 16, 2018 11:27 am
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
Re: Delete an item from wxListCtrl.
Posted: Sun Sep 16, 2018 12:49 pm
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.
Re: Delete an item from wxListCtrl.
Posted: Sun Sep 16, 2018 1:24 pm
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...
Re: Delete an item from wxListCtrl.
Posted: Sun Sep 16, 2018 9:38 pm
by dkaip
In Linux wxWidgets lib must have problem.
It must works on both OS.
Thank you
Jim.
Re: Delete an item from wxListCtrl.
Posted: Mon Sep 17, 2018 5:39 am
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);