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?
-
@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 35wxTextCtrl* TextCtrl1;
eingefügt habe, klappt das Compilieren. Das Ausführen von TextCtrl1->SetValue klappt aber noch nicht: Segmentation fault.
Danke für die Hilfsbereitschaft
-
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 istBind
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
ZeileButton1->Bind(wxEVT_BUTTON, &DBtoolFrame::OnButton1Click, this);
wxNewId()
ist deprecated. Wie geschrieben, nutzewxID_ANY
wenn es egal ist, welche ID das Control hat. Und sonst, setze selbst eine ID, die aber größer ist alswxID_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 Zeilenconst 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.