error: failed in AddChild(): AddChild() called twice

Are you writing your own components and need help with how to set them up or have questions about the components you are deriving from ? Ask them here.
Post Reply
User avatar
marco_84
Experienced Solver
Experienced Solver
Posts: 71
Joined: Mon Jul 08, 2019 7:30 pm
Location: Italy, Tuscany

error: failed in AddChild(): AddChild() called twice

Post by marco_84 »

Hello to all
I still need your help!
In the program that I make to keep gas and H2O consumption under control, I have a problem entering two dialogues, namely: "list of readings not sent", in italian language:"lista delle letture non inviate"

and "information on reading" in italian language: "informazioni sulla lettura", the first time I call them everything goes smoothly, but, I call this second time them a wxdebug dialog box that writes:

Code: Select all

./src/common/wincmn.cpp(1336): assert "!GetChildren().Find((wxWindow*)child)" failed in AddChild(): AddChild() called twice
pressing continue I get this error:

Code: Select all

./src/msw/window.cpp(1298): assert "!m_oldWndProc" failed in SubclassWin(): subclassing window twice?
this, stop my program! I forced to close it and restart

I don't know how to solve this problem,

on follow I post the first function: "list of readings not sent:"

Code: Select all

void progletture2 :: OnNonInviate (wxCommandEvent & event)
{
dlgnoninviate = Noninviate.Create(this, wxID_ANY, 
    wxT("Lista delle letture non inviate"), 
wxDefaultPosition, wxSize(400, 400)); 

Noninviate.nnoninviate = 0;
nulettura = elenco_letture->GetFirstItem();
while (nulettura)
{
nucontatore = elenco_letture->GetItemParent(nulettura);
if (nucontatore != elenco_letture->GetRootItem())
{
datiletcontatore = elenco_letture->GetItemText(nucontatore, COL_DATA);
datiletdatacomp = elenco_letture->GetItemText(nulettura, COL_DATA);
}
if (elenco_letture->GetItemText(nulettura, COL_INVIATO) == "No")
{
Noninviate.SetContatore (datiletcontatore);
Noninviate.SetDataLettura(datiletdatacomp);
Noninviate.SetNumLettura(elenco_letture->GetItemText(nulettura, COL_LETTURA));
Noninviate.init();
}
nulettura = elenco_letture->GetNextItem(nulettura);
}

  dlgnoninviate->Connect(ID_ninvlist, wxEVT_TREELIST_ITEM_ACTIVATED, 
      wxCommandEventHandler(noninviate :: OnActivate));

if (dlgnoninviate->Show(TRUE) == wxID_OK)
dlgnoninviate->Destroy();
}
on follow post two function:"information on reading"

Code: Select all

void noninviate :: OnActivate (wxCommandEvent & event)
{
int fatto = 0;
noninviateselected = lista_letture->GetSelection();
nulettura = elenco_letture->GetFirstItem();
while (nulettura)
{
if (lista_letture->GetItemText(noninviateselected, COL_CONTATORE) == elenco_letture->GetItemText(nulettura, COL_CONTATORE))
{
ShowInfo.SetInfoContatore(elenco_letture->GetItemText(nulettura, COL_CONTATORE));
while (fatto == 0)
{
nulettura = elenco_letture->GetNextItem(nulettura);
if (lista_letture->GetItemText(noninviateselected, COL_DATA_LETTURA) == elenco_letture->GetItemText(nulettura, COL_CONTATORE))
{
ShowInfo.SetInfoDataLettura(elenco_letture->GetItemText(nulettura, COL_CONTATORE));
ShowInfo.SetInfoNumLettura(elenco_letture->GetItemText(nulettura, COL_DATA_LETTURA));
ShowInfo.SetInfoInviato(elenco_letture->GetItemText(nulettura, COL_NUM_LETTURA));
fatto = 1;
}
}
}
nulettura = elenco_letture->GetNextItem(nulettura);
}

dlgshowinfo = ShowInfo.Create(this, wxID_ANY, 
"informazioni sulla lettura", 
wxDefaultPosition, wxSize(650, 350));

if (dlgshowinfo->Show(TRUE)== wxID_OK)
{
dlgshowinfo->Destroy();
}
}
thanks for your help

marco_84
I'm using: Ubuntu and Windows platform with wxwidgets 3.1.4
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: error: failed in AddChild(): AddChild() called twice

Post by doublemax »

It's not 100% clear because the types of some classes are not obvious, but i think the problem lies in these lines:

Code: Select all

dlgnoninviate = Noninviate.Create(this, wxID_ANY, 
    wxT("Lista delle letture non inviate"), 
wxDefaultPosition, wxSize(400, 400)); 

Code: Select all

dlgshowinfo = ShowInfo.Create(this, wxID_ANY, 
"informazioni sulla lettura", 
wxDefaultPosition, wxSize(650, 350));
You can not call Create() on the same object more than once.
Use the source, Luke!
User avatar
marco_84
Experienced Solver
Experienced Solver
Posts: 71
Joined: Mon Jul 08, 2019 7:30 pm
Location: Italy, Tuscany

Re: error: failed in AddChild(): AddChild() called twice

Post by marco_84 »

Hello Doublemax
thanks for your help

Can you help me and give info for correct this error? I can't do it myself, I called destroy to close the function but the error remains

marco_84
I'm using: Ubuntu and Windows platform with wxwidgets 3.1.4
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: error: failed in AddChild(): AddChild() called twice

Post by doublemax »

Show the code for Noninviate and ShowInfo. It looks as if these are classes that return a pointer to a dialog? Without knowing more, that doesn't make any sense to me.
Use the source, Luke!
User avatar
marco_84
Experienced Solver
Experienced Solver
Posts: 71
Joined: Mon Jul 08, 2019 7:30 pm
Location: Italy, Tuscany

Re: error: failed in AddChild(): AddChild() called twice

Post by marco_84 »

Hello Doublemax

Thanks

these are the function files that give error
Attachments
showinfo.cpp
(1.62 KiB) Downloaded 245 times
noninviate.h
(1.15 KiB) Downloaded 254 times
noninviate.cpp
(3.17 KiB) Downloaded 246 times
I'm using: Ubuntu and Windows platform with wxwidgets 3.1.4
User avatar
marco_84
Experienced Solver
Experienced Solver
Posts: 71
Joined: Mon Jul 08, 2019 7:30 pm
Location: Italy, Tuscany

Re: error: failed in AddChild(): AddChild() called twice

Post by marco_84 »

this last file
Attachments
showinfo.h
(1005 Bytes) Downloaded 268 times
I'm using: Ubuntu and Windows platform with wxwidgets 3.1.4
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: error: failed in AddChild(): AddChild() called twice

Post by doublemax »

Is there a special reason why you created these non-standard Create() methods that return a wxDialog* ? They make the code unnecessary complicated.

Unless you actually need the two-step creation (that's the only situation where the Create() method is used), don't use Create.

Just use a custom constructor for your dialog class and then use it like any other dialog. When using a custom dialog, the code should look like this:

Code: Select all

// create dialog on stack
noninviate dlgnoninviate(this, wxID_ANY, wxT("Lista delle letture non inviate"), wxDefaultPosition, wxSize(400, 400)); 
if( dlgnoninviate.ShowModal() == wxID_OK ) 
{
  // process dialog here
}
// no destruction of dialog needed
These two global instances of the dialogs are really bad. Don't do this.

Code: Select all

noninviate Noninviate;
showinfo ShowInfo;
Create a dialog on the stack when you need it.
Use the source, Luke!
User avatar
marco_84
Experienced Solver
Experienced Solver
Posts: 71
Joined: Mon Jul 08, 2019 7:30 pm
Location: Italy, Tuscany

Re: error: failed in AddChild(): AddChild() called twice

Post by marco_84 »

hello doublemax

I will call the dialog in stack mode
but you raised a problem at me:
These two global instances of the dialogs are really bad. Don't do this.
noninviate Noninviate;
showinfo ShowInfo;
how do I need to pass the treelist data from the other classes to "noninviate"?
verified that "noninviate" is a list of read to gas and h2o consumption that be sent to the managers.
for example in this case:

Code: Select all

Noninviate.nnoninviate = 0;
nulettura = elenco_letture->GetFirstItem();
while (nulettura)
{
nucontatore = elenco_letture->GetItemParent(nulettura);
if (nucontatore != elenco_letture->GetRootItem())
{
datiletcontatore = elenco_letture->GetItemText(nucontatore, COL_DATA);
datiletdatacomp = elenco_letture->GetItemText(nulettura, COL_DATA);
}
if (elenco_letture->GetItemText(nulettura, COL_INVIATO) == "No")
{
Noninviate.SetContatore (datiletcontatore);
Noninviate.SetDataLettura(datiletdatacomp);
Noninviate.SetNumLettura(elenco_letture->GetItemText(nulettura, COL_LETTURA));
Noninviate.init();
}
nulettura = elenco_letture->GetNextItem(nulettura);
}
here following the "Init" function of "noninviate":

Code: Select all

void noninviate :: init()
{
letture_noninviate[nnoninviate] = lista_letture->AppendItem(lista_letture->GetRootItem(), m_contatore);
lista_letture->SetItemText(letture_noninviate[nnoninviate], COL_DATA_LETTURA, m_datalettura);
lista_letture->SetItemText(letture_noninviate[nnoninviate], COL_NUM_LETTURA, m_numlettura);
nnoninviate++;
if (lista_letture->GetFirstItem() != lista_letture->GetRootItem())
lista_letture->Select(lista_letture->GetFirstItem());
}
how do I need pass data from "elenco_letture" of the function "main" to "lista_letture" of "noninviate"?

Code: Select all

wxString datiletcontatore, datiletdatacomp, datiletnumlettura;
wxTreeListItem nulettura, nucontatore;
these above are variables called in the "main" program constructor.

Code: Select all

wxTreeListCtrl * elenco_letture;
this above is called in global mode and so I don't like it!

thank you very much for your help and sorry if I waste your time

..... I solved with accessibility and now I practice



marco_84
I'm using: Ubuntu and Windows platform with wxwidgets 3.1.4
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: error: failed in AddChild(): AddChild() called twice

Post by doublemax »

Sorry, but the italian variable names make it really hard for me to follow the program logic.

Generally, if you have some data that needs to be accessed from multiple locations, there are not many options:
a) You pass a pointer to that data around through all hierarchy levels (which can be cumbersome).
b) a Singleton (Google it if you don't know what it is)
c) in wxWidgets, it's common to put the data into the global wxApp instance, accessible through a getter method
Use the source, Luke!
User avatar
marco_84
Experienced Solver
Experienced Solver
Posts: 71
Joined: Mon Jul 08, 2019 7:30 pm
Location: Italy, Tuscany

Re: error: failed in AddChild(): AddChild() called twice

Post by marco_84 »

I'll let you know how I solved it
sorry but it's just that I use wxwidgets

thanks for the suggestions
I will now do some tests following the book by "Julian Smart and Kevin Hock
with Stefan Csomor" which I found in Italian Language

marco_84
I'm using: Ubuntu and Windows platform with wxwidgets 3.1.4
User avatar
marco_84
Experienced Solver
Experienced Solver
Posts: 71
Joined: Mon Jul 08, 2019 7:30 pm
Location: Italy, Tuscany

Re: error: failed in AddChild(): AddChild() called twice

Post by marco_84 »

Hi Doublemax
Just use a custom constructor for your dialog class and then use it like any other dialog. When using a custom dialog, the code should look like this:

// create dialog on stack
noninviate dlgnoninviate(this, wxID_ANY, wxT("Lista delle letture non inviate"), wxDefaultPosition, wxSize(400, 400));
if( dlgnoninviate.ShowModal() == wxID_OK )
{
// process dialog here
}
// no destruction of dialog needed
I tried to make the constructor of the class "noninviate" in stack mode but I can't do it,
Can you post me an example of a constructor that can be called in stack mode?

I'm also satisfied with a minimal.cpp example


marco_84
I'm using: Ubuntu and Windows platform with wxwidgets 3.1.4
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: error: failed in AddChild(): AddChild() called twice

Post by doublemax »

You don't have to change much. Here are just the first few lines for noninviate.cpp/.h

Code: Select all

class NonInviate : public wxDialog
{
DECLARE_CLASS( noninviate )
public:
  NonInviate( wxWindow* parent,
              wxWindowID id = ID_viewnoninviate,
              const wxString& caption = wxT("Lista delle letture non inviate"),
              const wxPoint& pos = wxDefaultPosition,
              const wxSize& size = wxDefaultSize,
              long style = wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU );

Code: Select all

NonInviate::NonInviate( wxWindow* parent,
                        wxWindowID id,
                        const wxString &caption,
                        const wxPoint &pos,
                        const wxSize &size,
                        long style)
                       , wxDialog(parent, id, caption, pos, size, style )
{
wxStaticText * StaticText = new wxStaticText (this, wxID_STATIC,
wxT ( "Lista delle letture ancora da inviare ai gestori delle utenze"),
wxPoint(10, 20), wxSize(200, 20), wxALIGN_LEFT);
(I changed this without compiling it, so there could be typos)
Use the source, Luke!
User avatar
marco_84
Experienced Solver
Experienced Solver
Posts: 71
Joined: Mon Jul 08, 2019 7:30 pm
Location: Italy, Tuscany

Re: error: failed in AddChild(): AddChild() called twice

Post by marco_84 »

Hi Doublemax sorry if I answer you now but I could not connect

I solved it with your last post

Thanks for your help

marco_84
I'm using: Ubuntu and Windows platform with wxwidgets 3.1.4
Post Reply