wxObject is an ambiguous base of MyFrame



  • Hallo

    Ich habe das Problem, das wenn ich mit den Befehl Connect() auf ein Element verbinden will, die Fehler Meldung "wxObject is an ambiguous base of Frames" kommt.

    Mein Programm is so aufgebaut:

    ///////////////////////////////////////////////////////////////////////
    //mainwindow.h
    
    class MainWindow : public wxFrame
    {
    
    	public:
    		MainWindow(wxWindow *parent, wxWindowID id = 1,const wxString &title = wxT("IRC Client"), const wxPoint& pos = wxDefaultPosi[code]tion , const wxSize& size = wxDefaultSize, long style = MainWindow_STYLE);
            virtual ~MainWindow();
    
    	private:
    		void CreateGUI();        
    
        protected:
    
            //Hier sind Buttons, Lables, und andere Objekte deklariert
            //...
    
       protected:
            enum
            {
                //IDs von den Objekten
               //...
            };
    [/code]
    };
    
    /////////////////////////////////////////////////////////////////////
    //dialog.h
    
    class DialogLogin : public wxDialog{
    
        public:
    		DialogLogin(wxWindow *parent, wxWindowID id = 1, const wxString &title = wxT("Login"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style =DialogLogin_STYLE);
    		virtual ~DialogLogin();
    
        private:
            void CreateGUI();        
    
        protected:
    
            //Deklaration von den Objekten
            //...
    
        protected:
            enum
            {
               //IDs von den Objekten
               //...
            };
    };
    
    /////////////////////////////////////////////////////////////////////////
    //frames.h
    
    #include "mainwindow.h"
    #include "dialog.h"
    
    class Frames : protected MainWindow, protected DialogLogin{
    
        public:
            //Hier werden die Events von den Objekten deklariert. z.B.
            void OnMainWindowClose(wxCloseEvent&);        
            //...
    
            Frames() : MainWindow(NULL),DialogLogin(NULL){
                fMain = new MainWindow(NULL);
                fMain->Show();
    
                dLogin = new DialogLogin(NULL);
                dLogin->Show();
            }
    
        private:               
            MainWindow *fMain;
            DialogLogin *dLogin;
    
        protected:
    
           //gemeinsam genutzte Objekte von MainWindow und DialogLogin
           //...
        protected:
           enum{
               //IDs von den gemeinsam genutzen Objekten
               //...
          };
    
    };
    
    //////////////////////////////////////////////////////////////////////
    //init_gui.cpp
    
    void MainWindow::CreateGUI(){
    
         /*Hier werden die Objekte mit new erstellt und hier soll 
         zu den Objekten verbunden werden*/
    
        /*z.B. Connect(ID_BTNCANCEL02,wxEVT_COMMAND_BUTTON_CLICKED ,(wxObjectEventFunction)(&Frames::OnMainWindowClose));*/
    
    }
    
    void DialogLogin::CreateGUI(){
      //Das selbe wie oben...
    
    }
    

    Danke schon mal im Vorraus.


  • Mod

    Deine Ableitung ist Falsch. Auch solltest du immer nur in einer Ist-ein Relation ableiten, hier liegt aber bei Frames ein hat-ein vor.



  • Danke für die schnelle Antwort, aber so ganz klar ist mir das jetzt nicht.
    Wie würde den der Code richtig aussehen oder müsste ich den Code komplett umschreiben?


  • Mod

    Du solltest nicht von 2 Klassen gleichzeitig ableiten, wenn diese ein gemeinsames Parent haben.
    Das nennt man auch "diamond of death", da diese Ableitung eher unglücklich ist.

    Wenn du Ableitest dann immer in einem ist ein relation:
    Dein Dialog ist ein Dialog. Dein Frame ist ein Frame.
    Aber deine Framesklasse kann nicht Dialog _und_ Frame sein.
    Deine Frames Klasse hat eher einen Frame und einen Dialog.
    Du solltest hier also auf die Ableitung verzichten.

    Und schau dir evtl. mal GUI Editoren an, wie wxSmith in Code Blocks.

    phlox



  • Ok, das klingt logisch.
    Mein Grundproblem ist eigentlich: Wie kann ich von einem Fenster auf die Objekte von einem anderen Fenster, also eben eines Dialogfensters zugreifen und verändern?


  • Mod

    Du musst dem Fenster einen Zeiger oder eine Referenz auf das Objekt geben. Oder den Dialog lokal erstellen.

    class MyFrame;
    class MyDialog;
    
    class MainFrame : public wxFrame
    {
    MyFrame* myframe;
    
    MainFrame(/* parameter*/)
    {
      myframe = new MyFrame(this,wxNewId(),"Titel");
    }
    
    void OnShowDialog(wxCommandEvent& e)
    {
      MyDialog mydialog;
    if(mydialog.ShowModal() == wxID_OK)
      //dialog wurde mit ok beendet.
    }
    
    };
    

    phlox



  • Müssen dann aber nicht die Objekte von den einen Fenster auf den das andere zugreifen will nicht public sein? Und wie deklariere ich die Events wenn die in einer anderen Klasse liegen?


  • Mod

    Stony92 schrieb:

    Müssen dann aber nicht die Objekte von den einen Fenster auf den das andere zugreifen will nicht public sein?

    Nein, Elemente einer Klasse sind niemals public!
    Wenn du zugriff auf ein Objekt brauchst, musst du der Klasse jeweils ein eigenen Zeiger auf das Objekt geben, oder in einer Methode übergeben.

    MyDialog::Update(Data* data)
    {}//Dialog updaten.
    

    Aber generell solltest du dich vielleicht erstmal mit OOP und den Konzepten von C++ beschäftigen.

    Und wie deklariere ich die Events wenn die in einer anderen Klasse liegen?

    Du kannst events per connect an andere Klassen binden.

    phlox



  • Ich habe jetzt versucht das Programm so hinzubekommen, wie du es mir empfohlen hast. Sry aber ich stehe jetzt vor einem weiteren Problem:
    Mit Connnect() habe ich die Events jetzt an den Objekten gebunden und das Problem ist jetzt, dass der Zeiger von MainWindow ins Nichts zeigt, der Zeiger vom Dialogfenster aber funkt.

    //events.h
    
    class Events : public wxEvtHandler{
    
        public:
            Events() : wxEvtHandler(){
                fMain = new MainWindow(NULL);
                fMain->Show();            
    
                dLogin = new DialogLogin(NULL);
                dLogin->Show();
    
                InitEvents();
            }
    
        private:
            void InitEvents();
    
            MainWindow *fMain;
            DialogLogin *dLogin;
    
        protected:        
            void BtnConnectClick(wxCommandEvent& event);
            void BtnCancel02Click(wxCommandEvent& event);
            void BtnSendClick(wxCommandEvent& event);
    
    };
    
    //events.cpp
    void Events::InitEvents(){
    
        dLogin->BtnConnect->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(Events::BtnConnectClick));
        dLogin->BtnCancel02->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(Events::BtnCancel02Click));   
        fMain->BtnSend->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(Events::BtnSendClick));
    
    }
    

    Nun versuche ich in z.B. BtnCancel02Click() auf fMain zuzugreifen, was aber zum Programmabsturz führ.

    void Events::BtnCancel02Click(wxCommandEvent& event){
        fMain->~MainWindow(); //Hier stürzt das Programm ab
        dLogin->~DialogLogin();
    }
    


  • Du musst der Connect-Methode auch den Event-Sink übergeben, in dem Fall einen Zeiger auf Deine eigene Klasse, also this . Das sieht dann so aus:

    void Events::InitEvents(){
    
        dLogin->BtnConnect->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(Events::BtnConnectClick), (wxObject*)0, this);
        dLogin->BtnCancel02->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(Events::BtnCancel02Click), (wxObject*)0, this);  
        fMain->BtnSend->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(Events::BtnSendClick), (wxObject*)0, this);
    
    }
    

    Siehe hier: http://docs.wxwidgets.org/trunk/classwx_evt_handler.html#a290d9b67348e74c1da8497955a4e35c

    @phlox: Ist es eigentlich schlechter Stil, Destruktoren direkt aufzurufen? Alternativen?



  • Danke!!
    Jetzt klappt alles 🙂 .



  • Hallo

    mikey schrieb:

    @phlox: Ist es eigentlich schlechter Stil, Destruktoren direkt aufzurufen? Alternativen?

    Ja den Destruktor direkt aufrufen ist afaik nicht gültig. Stattdessen lieber den Operator delete benutzen, bzw. für die GUI-Elemente von wxWidgets besser die Destroy-Methode.

    bis bald
    akari



  • thx akari, dann weiß ich Bescheid.


Log in to reply