not declared in this scope



  • Ich versuche, meine kleine java-FX Auftragsbearbeitung in C++ neu zu entwickeln.
    Um C++ besser zu lernen verwende ich dazu den Editor Geany, keine IDE.
    Dabei führt die Methode, die per Button das Schreiben in TextFelder auslösen soll,
    beim Kompilieren zu einem 'was not declared in this scope' Fehler.
    Da mein Programm sehr umfangreich ist, versuchte ich anhand eines Beispiels aus
    dem Internet zu ergründen, woran das liegt. Nachdem ich dort einen weiteren Button
    und ein Textfeld eingefügt hatte, trat der Fehler auch auf, kommentiere ich die
    betreffende Zeile aus, startet das Testprogramm. Was kann ich tun, um die Felder
    richtig zu deklarieren, dass die vom Button gestartete Methode sie kennt.
    hier der Code

    #include <wx/wx.h>
    
    class MyFrame : public wxFrame
    
    {
    public:
        MyFrame() : wxFrame(NULL, wxID_ANY, "Test", wxPoint(500,500), wxDefaultSize)
        
        {
            
            wxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
            sizer->Add(new wxStaticText(this, wxID_ANY, "Schrift anpassen ->"), wxSizerFlags().Border().Centre());
            //added begin
            wxButton* Button1 = new wxButton(this, wxID_ANY, _("Write Text"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON1"));
            Button1->SetForegroundColour(wxColour(255,30,30));
            wxFont Button1Font(12,wxFONTFAMILY_SWISS,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL,false,_T("Sans"),wxFONTENCODING_DEFAULT);
            Button1->SetFont(Button1Font);
            Button1->Bind(wxEVT_BUTTON, &MyFrame::OnButton0, this),
            sizer->Add(Button1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
            
            wxTextCtrl* TextCtrl1 = new wxTextCtrl(this, wxID_ANY, _("..."), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TEXTCTRL1"));
            TextCtrl1->SetToolTip(_("Anrede"));
            sizer->Add(TextCtrl1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
            //added end
            wxButton* btn = new wxButton(this, wxID_ANY,  "Schrift gross");
            btn->Bind(wxEVT_BUTTON, &MyFrame::OnButton1, this),
            sizer->Add(btn, wxSizerFlags().Border().Centre());
            wxButton* btn2 = new wxButton(this, wxID_ANY, "Schrift klein");
            btn2->Bind(wxEVT_BUTTON, &MyFrame::OnButton2, this),
            sizer->Add(btn2, wxSizerFlags().Border().Centre());
            SetSizerAndFit(sizer);
            Show(true);
        }
    
         void OnButton0(wxCommandEvent& event)
        {
           TextCtrl1->SetValue("Test erfolreich!");  // error trigger
        }
    
    
        void OnButton1(wxCommandEvent& event)
        {
            for ( wxWindowList::iterator it = GetChildren().begin(); it != GetChildren().end(); ++it )
                (*it)->SetFont((*it)->GetFont().Larger());
    
            Fit();
        }
        void OnButton2(wxCommandEvent& event)
        {
            for ( wxWindowList::iterator it = GetChildren().begin(); it != GetChildren().end(); ++it )
                (*it)->SetFont((*it)->GetFont().Smaller());
    
            Fit();
        }
    };
    
    class MyApp : public wxApp
    {
    public:
        virtual bool OnInit() { new MyFrame; return true; }
    };
    
    wxIMPLEMENT_APP(MyApp);
    
    

    Danke für jede Hilfe



  • Du mußt die Variable TextCtrl1 zu einem Member der Klasse machen.



  • @Th69
    hallo, ich bin mit C++ und wxWidgets noch am Anfang. Anhand des Codes glaubte ich, das Textfeld sei deklariert und damit Member. Was muss ich ändern?


  • Mod

    @gokusa sagte in not declared in this scope:

    @Th69
    hallo, ich bin mit C++ und wxWidgets noch am Anfang. Anhand des Codes glaubte ich, das Textfeld sei deklariert und damit Member. Was muss ich ändern?

    Eine Variable im Konstruktor ist nur das: Eine Variable im Konstruktor. Alles was du nach den öffnenden { in Zeile 9 definierst, existiert nur bis zum abschließenden } in Zeile 33. Eine Membervariable müsste halt außerhalb der Memberfunktionen, aber innerhalb der Klasse, definiert werden. Also irgendwo zwischen dem { in Zeile 5 und dem } in Zeile 55. Natürlich unter Beachtung in welcher Sichtbarkeitssektion du das haben möchtest, public oder private.

    Das ist sehr grundlagig. Ich empfehle ganz dringend, dass du zuerst C++ lernst, bevor du mit einem Widgetframework anfängst, das noch irgendwelchen Sonderregeln gehorchen kann. Beispielsweise sieht der Code für einen normalen C++-Programmierer nach extremem Speicherleck aus, aber vielleicht hat wxWidgets da irgendwelche Sonderregeln und das ist ok so (Ich spreche nicht wxWidgets, daher weiß ich die Antwort nicht). Das heißt, du musst genau wissen und verstehen, was du da tun darfst und was nicht. Wozu du logischerweise erst einmal die normalen Grundlagen von C++ kennen musst.



  • @gokusa: Der Code würde doch auch in Java genauso eine Fehlermeldung liefern - auch dort bräuchtest du eine Member Variable: Declaring Member Variables

    In C++ ist das ähnlich, nur daß man nicht bei jedem Member explizit den Zugriffsmodifizierer angeben muß, sondern dieser gilt dann für ganze Bereiche, z.B.

    class Test
    {
    private:
      int x;
      bool b;
      double d;
    
    public:
      // ...
    };
    

    Schau auch mal in die Linkliste.



  • @gokusa sagte in not declared in this scope:

    Um C++ besser zu lernen verwende ich dazu den Editor Geany, keine IDE.

    Ich glaube nicht, dass das zielführend ist. Eine IDE hätte dich auf das Problem hinweisen können. Die IDE ist ein Werkzeug, welches sich lohnt direkt mit zu lernen, zumindest meiner Meinung nach.

    @SeppJ sagte in not declared in this scope:

    aber vielleicht hat wxWidgets da irgendwelche Sonderregeln und das ist ok so (Ich spreche nicht wxWidgets, daher weiß ich die Antwort nicht)

    Ja, genau das. wxWidgets Klassen, die einen wxWidgets Parent mitbekommen werden von wxWidgets verwaltet, d.h. da darf man Speicher nicht ohne weiteres selbst wieder frei geben.



  • @Schlangenmensch @Th69 @SeppJ
    danke für die Antworten. Zum besseren Verständnis: Was das Lernen betrifft, an Büchern habe ich BREYMANN: C++ programmieren und Torsten T. Will C++ Das umfassende Handbuch. Begonnen habe ich mit kleinen Consolenprogrammen, danach erste GUI-Versuche mit Code::Blocks und wxWidgets. Dort bin ich soweit gekommen, dass der Nachbau meines JavaFX Programms startet, durch erste Methoden mit Buttons eine PostgreSQL- Datenbank-Verbindung aufgebaut und das Result in die Felder geladen wird. Dann kam ich nicht weiter, weil ein Zweites Result in die Rows eines Tabellen-Grids eingefügt werden soll. Dieses Grid muss dazu wohl angepasst werden, was aber schwierig ist, wenn man schon den von Code::Blocks erstellten Code nicht vollends versteht. So kam es, eben um die Grundlagen besser zu verstehen, zu dem Experiment in Geany. Der gepostete Test diente nur der Darstellung des Fehlers. Zurück dazu, es liegt wohl an wxWidgets:
    Nachdem ich in Zeile 35

    wxTextCtrl* TextCtrl1;
    

    eingefügt habe, klappt das Compilieren. Das Ausführen von TextCtrl1->SetValue klappt aber noch nicht: Segmentation fault.
    Danke für die Hilfsbereitschaft


  • Mod

    Zeigt dein Zeiger denn irgendwo hin? Irgendein Objekt musst du ihm vorher schon noch zuweisen.

    Wie ich sagte: Das sind dermaßen grundlegende Dinge, du hantierst hier mit Sprengstoff, ohne es jemals gelernt oder geübt zu haben.



  • @SeppJ
    tut mir leid, ich hätte die vollständige Zeile angeben sollen:

    TextCtrl1->SetValue(" mein neuer Text ");
    


  • Du mußt dann auch die Zeile mit der Variablen-Initialisierung anpassen:

    TextCtrl1 = new wxTextCtrl(...);
    

    Also den Typ wxTextCtrl* löschen, damit keine neue (lokale) Variable gleichen Namens angelegt wird!
    Das sind aber Grundlagen, welche auch in Java so gelten...



  • @gokusa ich bin kein Freund von generiertem Code. Insbesondere, wenn man nicht mit Default Sachen auskommt. Ich meine auch Code::Blocks empfiehlt noch wxWidgets 2.8. Als ich vor 5 Jahren ungefähr das erste mal mit wxWidgets in Berührung kam, war schon 3.1 draußen. Aktuell ist 3.2.

    Aber, Grundlagen wie Variablen Scope und so sollten schon da sein, da unterscheiden sich C++ und Java auch nicht so stark von einander.



  • @Th69
    Die Schreibweise für Member-Variablen war schon richtig:

    wxTextCtrl* TextCtrl1;
    

    Sie allein reicht im Konstruktor aber nicht, man muss auch die wxID angeben:

    const long ID_TEXTCTRL1 = wxNewId();
    

    Mehr zu wxWidgets habe ich hier gefunden:
    https://www.wxwidgets.org/docs/book/
    und die über 600 Seiten starke Anleitung (englisch) als PDF heruntergeladen:
    Cross-Platform GUI Programming with wxWidgets.pdf
    Die dort beschriebene Lösung des Event-Handlings mit Connect brachte nach einigen Fehlversuchen wegen Syntaxfehlern
    dann die Lösung, ich habe den eingangs geposteten Code auf das Wesentliche gekürzt:

    #include <wx/wx.h>
    
    class DBtoolApp : public wxApp { 
        public:
            bool OnInit();
    };
    
    class DBtoolFrame : public wxFrame {
        public:
            DBtoolFrame();
            void OnButton1Click(wxCommandEvent& event);
            const long ID_BUTTON1 = wxNewId();
            const long ID_TEXTCTRL1 = wxNewId();
        private:
            wxPanel* mainPanel;
            wxBoxSizer* mainBoxSizer;
            wxTextCtrl* TextCtrl1;
            wxButton* Button1;
    };
    
    IMPLEMENT_APP(DBtoolApp)
     
    bool DBtoolApp::OnInit() {
        DBtoolFrame *dbtoolFrame = new DBtoolFrame;
        dbtoolFrame->Show();
        SetTopWindow(dbtoolFrame);
        return true;
    }
    
    DBtoolFrame::DBtoolFrame() : wxFrame(nullptr, wxID_ANY, "Test-Tool") {
        mainPanel = new wxPanel(this, wxID_ANY);
        mainBoxSizer = new wxBoxSizer(wxHORIZONTAL);
        
        Button1 = new wxButton(mainPanel, ID_BUTTON1, "Write Text");
        Button1->SetForegroundColour(wxColour(40,30,200));
        mainBoxSizer->Add(Button1, 1, wxALL, 20);
        
        TextCtrl1 = new wxTextCtrl(mainPanel, ID_TEXTCTRL1, "...", wxDefaultPosition, wxDefaultSize);
        mainBoxSizer->Add(TextCtrl1, 1, wxALL, 20);
        
        mainPanel->SetSizer(mainBoxSizer);
        mainBoxSizer->SetSizeHints(this);
        SetSize(500, 400);
        TextCtrl1->SetFocus();
        Button1->SetDefault();
        Layout();
        Connect(ID_BUTTON1,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&DBtoolFrame::OnButton1Click);
    }
    
     void DBtoolFrame::OnButton1Click(wxCommandEvent& event)
        { 
           wxString txt;
           txt = "mein neuer Text";
           TextCtrl1->SetValue(txt);
        }
    

    Danke für die Hilfe



  • @gokusa Achtung, Connect ist zwar nicht ausdrücklich depricated, aber trotzdem veraltet. Aktueller ist Bind Das ganze PDF würde ich mit vorsicht genießen, dass ist von 2006.

    Du brauchst auch nicht unbedint eine ID. Der default wxID_ANY reicht häufig aus.

    Versuch mach, anstelle der Connect Zeile

    Button1->Bind(wxEVT_BUTTON, &DBtoolFrame::OnButton1Click, this);
    

    wxNewId() ist deprecated. Wie geschrieben, nutze wxID_ANY wenn es egal ist, welche ID das Control hat. Und sonst, setze selbst eine ID, die aber größer ist als wxID_HIGHEST.



  • @Schlangenmensch
    hallo und danke für den Hinweis, ich werde mich am Wochende wieder damit befassen. In dem mit Code::Blocks und wxWidgets (3.0) erstellten Code wurde sowohl wxNewId() als auch Connect benutzt und ich glaubte, die Anleitung (PDF) wäre aktuell. Inzwischen habe ich die neuere Version im HTML Format gefunden und werde mich nur noch nach dieser richten. Ein Grund mehr, erstmal nur mit dem Editor die Grundlagen zu erlernen.



  • @Schlangenmensch
    deinen Empfehlungen folgend habe ich die Zeilen

    const long ID_BUTTON1 = wxNewId();
    const long ID_TEXTCTRL1 = wxNewId();
    

    und

    Connect(ID_BUTTON1,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&DBtoolFrame::OnButton1Click);
    

    entfernt und beim Button Bind hinzugefügt.

    Button1->Bind(wxEVT_BUTTON, &DBtoolFrame::OnButton1Click, this);
    

    Es funktioniert, Danke. Mein eingangs geposteter Code mit ->Bind enthielt strukturelle Fehler, das konnte nicht klappen.


Anmelden zum Antworten