Reaktion auf ButtonClick
-
freakC++ schrieb:
Das Problem ist nun, dass list unbekannt ist. Ich kann list ja auch nicht als Paramenter von Button1Click schreiben. Wie mache ich also list bekannt?
Membervariablen und/oder Getter/Setter sind dir aber bekannt?
cu André
-
schon, aber ich habe in diesem konkreten Fall meine Schwierigkeiten, wegen Button1Click!
Ich denke, dass die Lösung mir bekannt ist, aber ich komm wiedermal nicht drauf.
Ich hoffe auf eure Hilfe!!
Vielen Dank
lg,freakC++
-
Wie asc schon gesagt hat, mach list zum Member von TForm1.
-
freakC++ schrieb:
schon, aber ich habe in diesem konkreten Fall meine Schwierigkeiten, wegen Button1Click!
Wo gehört die list logisch hin? Danach entscheidest du ob sie ein Member der Form (Zugriff über Member), oder eines anderen Objektes ist (Zugriff über Getter, wobei du dann natürlich auch dieses Objekt als Member in der Form haben musst).
cu André
-
hallo,
danke für euren zahlreichen Tipps. Wenn ich jedoch nochmal genau nachdenke, muss ich gestehen, dass ich Membervariabeln verwechselt habe. Könnt ihr mir nochmal auf die Sprünge helfen, was ihr genau meint.
Ich hab die Vereinbarung von der Stringliste schon in die Klassenvereinbarung und sonst wo hin geschrieben, aber das hat nicht sehr viel gebracht.Ich hoffe auch euer Verständnis!!
Vielen Dank
lg,freakC
-
Suche die Headerdatei in der TForm1 deklariert ist. Dort suchst du in der Deklaration von TForm1 (class TForm1 ...) nach private:
Da drunter kommen die Deklarationen aller privaten Membervariablen von TForm1 also auch die deiner list. Da es eine TStringList-Instanz sein soll muß das natürlich ein Zeiger sein.class TForm1 : public TForm { __published: // Von der IDE verwaltete Komponenten // hier sind alle von der IDE erzeugten Member private: // Anwender-Deklarationen TStringList* list; //hier ist deine Liste
Damit du deine Liste auch verwenden kannst, mußt du sie noch allozieren. Dies machst du am besten im Konstruktor.
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner), list(new TStringList) //hier wird Speicher für deine Liste vereinbart { }
Den da vereinbarten Speicher mußt du zum Schluß noch freigeben. Dazu erzeugt man am besten einen Destruktor für TForm1 (gibt es standardmäßig nicht. Dazu schreibst du in deine cpp
__fastcall TForm1::~TForm1() { delete list; }
Der Destruktor muß natürlich noch in der Headerdatei deklariert werden.
-
freakC++ schrieb:
Ich hab die Vereinbarung von der Stringliste schon in die Klassenvereinbarung und sonst wo hin geschrieben, aber das hat nicht sehr viel gebracht.
Vielleicht solltest du dir vorsichtshalber noch mal ein Grundlagenbuch anschauen, da dies C++ Grundlagenwissen ist. Membervariablen sind Variablen die Objektbezogen gelten, und alle Methoden der Klasse können auf diese zugreifen (statische Methoden nur auf statische Membervariablen, da diese Klassen- und nicht Objektbezogen sind).
Demzufolge müsste deine Liste damit du diese in dem Event verwenden kannst entweder eine Membervariable der Klasse sein (Da das Event nicht statisch sein wird kann kann die Membervariable entweder nicht-statisch oder statisch sein). Dann kannst du diese wie eine lokale Variable in der Methode verwenden... Eine andere Alternative wäre eine globale Variable, das ist aber in der Regel niemals eine gute Lösung (ich verwende niemals globale Variablen, es sei den diese sind vom Framework vorgesehen).
Eine weitere Möglichkeit ist natürlich noch das man diese Über eine Funktion bzw einer Methode einer anderen Klasse erhält, auf die man in der Klasse Zugriff hat.
cu André
-
Hallo zusammen,
vielen Dank für eure Antworten. Ja, ich bin noch ein Anfänger und habe dementsprechend auch noch ein Anfängerbuch und werde auch noch einige andere durchnehmen. Ein Problem ist, dass Fremdwörter wie Member nicht angesprochen werden, aber dennoch durchgenommen werden - halt nur unter anderem Namen...
An Braunstein: Ich habe zuvor schonmal meine StringList unter private von TForm1 deklariert und den Speicherplatz (mit new) in der FormCreate - Methode reserviert. Also ziemlich ähnlich zu deiner Variante. Ich habe jedoch deinen Lösungsvorschlag 1 zu 1 übernommen. Leider plagen mich nun drei andere Fehler:
Konvertierung von 'TStringList *' nach 'TCelirity *' nicht möglich (im Konstrukror)
Konvertierung von 'TStringList *' nach 'TCelirity *' nicht möglich (in Button1Click - Methode)
Keine Übereinstimmung des Typs beim Parameter 'list' ('TStringList *' erwartet, 'TCelirity *' erhalten) (in Button1Click - Methode)
Kann es sein, dass es noch Schwierigkeiten mit der Deklaration gibt, da ich TStringList *list ja auch als Parameter von Celirity1->Save stehen habe. Oder woran liegt der Fehler?
Hier nochmal die Button1Click - Methode:
void __fastcall TForm1::Button1Click(TObject *Sender) { Celirity1->Save(list, StringGrid, StringGrid1); }
Vielen Dank für eure Hilfe
lg, freakC++
-
Kann es sein, dass du eine Variable mit Name "list" vom Typ TCelirity * hast? Das sagen zumindest die Fehlermeldungen.
-
Ne, hab ich nicht. Jedoch habe ich in der TCelirity - Klasse folgende Methode mit folgenden Parametern:
void __fastcall Save (TStringList *list, TStringGrid *grid, TStringGrid *grid1);
Hier wird also auch die StringList vereinbart, wobei das auch zwingend notwendig ist, da ich diese ja für die Save - Methode brauche.
Vielen Dank für eure Hilfe
lg, freakC++
-
Schau bitt nochmal genau nach. es kann eigentlich nicht anders sein. Zur Not kannst du mir ja mal dein Projekt schicken.
-
Hallo zuammen,
ich habs geschafft. Wie Braunstein schon vermutet hat, hat sich noch ein Flüchtigkeitsfehler eingeschlichen. Danke für dein Angebot, Braunstein.
Damit ist das Problem gelöst. Wie es aber so ist, habe ich noch zum gleichen Programm und zum gleichen Quelltext eine andere Frage. Da die Überschrift dieses Threads noch passt, öffne ich keinen neuen. Wie ihr vll. schon aus dem Quelltext erfahren habt möchte ich, dass wenn ich auf Button1 klicke eine StringGrid ausgelesen wird und in einer Stringliste gespeichert wird. Wenn ich auf Button2 klicke, soll StringGrid2 ausgelesen werden und auch in einer Stringliste gespeichert werden. Da beide Buttons die gleiche Methode nutzen, habe ich zur Unterscheidung die Variabel Pressed vom Typ bool eingeführt. Wenn ich nun Button2 klicke wird diese auf true gesetzt, sonst ist sie auf false:void __fastcall TCelirity::Save(TStringList *list, TStringGrid *grid, TStringGrid *grid1) { const String Leer = ". "; const String Leer1 = ". "; if (Pressed == true) { for (int p=1; p<32; p++) { if (p>9) list->Add ( IntToStr (p) + Leer1 + grid1->Cells[1][p] + Leer); else list->Add ( IntToStr (p) + Leer + grid1->Cells[1][p] + Leer1); } } else { for (int p=1; p<15; p++) { if (p>9) list->Add ( IntToStr (p) + Leer1 + grid->Cells[1][p] + Leer); else list->Add ( IntToStr (p) + Leer + grid->Cells[1][p] + Leer1); } } list->SaveToFile ("Wertetabelle.dat"); list->SaveToFile ("Wertetabelle.txt"); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { Celirity1->Pressed == true; //Wert wird auf true gesetzt, wodurch bei der Save //Methode eine Entscheidung getroffen werden kann Celirity1->Save(list, StringGrid, StringGrid1); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { Celirity1->Save(list, StringGrid, StringGrid1); } //---------------------------------------------------------------------------
Wenn ich nun auf Button1 klicke, wird die korrekte Stringliste von StringGrid1 angelegt. Wenn ich aber auf Button2 klicke, wird die gleiche StringList erstellt (also kein Unterschied zu Button1). Egal welchen Button ich klicke, es wird nur der else-Zweig von Save ausgeführt.
Funktioniert das mit Pressed nicht so, oder woran liegt der Fehler?
Vielen Dank
lg, freakC++
-
Wird denn im Click-Event des Button2 Button2Click() oder Button1Click() aufgerufen? Button kopiert und nicht angepaßt?
-
ne, ich habe extra nochmal die beiden Buttons durch neue ausgetauscht. Also daran kann es nicht liegen? Woran kann es dann liegen?
Vielen Dank für eure Hilfe
lg, freakC++
-
freakC++ schrieb:
ne, ich habe extra nochmal die beiden Buttons durch neue ausgetauscht. Also daran kann es nicht liegen? Woran kann es dann liegen?
1. Zum einen Änderst du den Status des Flags nicht zurück (Celirity1->Pressed).
2. Wenn der Wert nur zur Entscheidung innerhalb einer Methode dient: Warum setzt du diesen nicht zurück? Und warum übergibst du zwei Grids wenn du nur eines pro Fall brauchst...
3. Sprechende Variablennamen würden dir selbst und auch dem Leser helfen (Was bedeuted "Pressed" in diesem Fall, was bedeutet eigentlich "Celirity"...).
4. Bei doppelten Code habe ich immer so ein Kribbeln in den Fingern...// Ich weiß zwar nicht was dein Code machen soll, und wieso die Anzahl abhängig // vom Grid fest "eingebrannt" ist, und warum du nicht gegen die Anzahl // Zellen prüfst... Aber vielleicht mal eine Alternative void __fastcall TCelirity::Save(TStringList *stringList, TStringGrid *grid, int cellCount) { const String leer1 = ". "; const String leer2 = ". "; for(int gridIndex=1; gridIndex<9; ++gridIndex) list->Add(IntToStr(gridIndex) + leer2 + grid->Cells[1][gridIndex] + leer1); for(int gridIndex=9; gridIndex<cellCount; ++gridIndex) list->Add(IntToStr(gridIndex) + leer1 + grid->Cells[1][gridIndex] + leer2); list->SaveToFile ("Wertetabelle.dat"); list->SaveToFile ("Wertetabelle.txt"); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { Celirity1->Save(list, StringGrid1, 32); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { Celirity1->Save(list, StringGrid, 15); } //---------------------------------------------------------------------------
-
Hallo,
also ich bin zutiefst beeindruckt. Auf solch eine Lösung wäre ich gar nicht gekommen: Respect ascJa, mir kribbelt es auch bei doppelten Quelltext in den Fingern, aber ich wollte Schönheitsfehler zunächst außen vor lassen und mich auf das Wesentliche beschränken. Nun hast du gleich ein weiteres Problem gelöst!
Wegen den Ausdrücken: Celirity heißt einfach nur Geschwindigkeit, da das Programm Rotationsgeschwindigkeiten berechnen soll...
Mit Pressed wollte ich nur einen gedrückten Button beschreiben.Noch eine Frage: Wie schon gesagt, wäre ich auf eine solche (für mich geniale) Lösung nicht gekommen. Da ich noch ein Anfänger bin, beschreite ich, wie man sieht, umständlichere Wege. Doch hoffe ich, dass auch hier gilt "Übung macht den Meister", denn ich fände es natürlich toll, wenn ich irgendwann auf so etwas auch kommen würde!!
Ich hoffe, dass ihr mir zustimmt, dass einfach nur Erfahrung benötigt wird, um anders (wie asc es getan hat) an ein solches Problem zu gehen!!!
Vielen Dank für eure Hilfe
lg, freakC++
-
freakC++ schrieb:
Wegen den Ausdrücken: Celirity heißt einfach nur Geschwindigkeit, ...
Nein, mit Sicherheit nicht
Mein Englisch mag zwar nicht gut sein, aber Celerity trifft es eher (Lieber mit www.leo.org & co kurz nachschauen). Celirity gibt es nicht
freakC++ schrieb:
Mit Pressed wollte ich nur einen gedrückten Button beschreiben.
Das ist mir schon klar, aber was sagt der Name aus? Mhh, okay, ein Button wurde gedrückt, und nun?
Mal ein beispiel für Variablennamen die ich verwende, ohne Angaben von dem Typ oder den Sinn: address, list.isEmpty, addressWindow.hasEditRight...
Was ist nun lesbarer? Nenne eine Variable lieber nach ihren Sinn. In dem Fall nicht Pressed, sondern was sie im Programmfluß bedeuten soll.freakC++ schrieb:
Da ich noch ein Anfänger bin, beschreite ich, wie man sieht, umständlichere Wege...
War auch nicht unbedingt als Kritik gemeint, sondern als Hilfe
freakC++ schrieb:
Ich hoffe, dass ihr mir zustimmt, dass einfach nur Erfahrung benötigt wird, um anders (wie asc es getan hat) an ein solches Problem zu gehen!!!
Ich lerne auch noch tagtäglich hinzu, und ich Programmiere nun seit 20 Jahren (professionell erst etwa 10).
cu André
P.S: Noch ein Nachtrag: Du wirst auch erst mit der Zeit einen guten Programmierstil finden, ggf. auch mehrfach in deinem Leben ändern. Aber immer gut ist es wenn er lesbar ist. Ich hatte mal irgendwann ein kleines Programm ausgedruckt in zwei Stilen, und einen Nicht-Programmierer gefragt was es wohl macht (insgesamt eine Seite Code). Seine erste Reaktion war "ich kann nicht programmieren", er hatte sich den Code aber dennoch angeschaut und tatsächlich einen von den Beiden weitgehend verstanden. Wohl bemerkt ohne Programmieren zu können. Kleines Beispiel: if(addressBook.isEmpty()) ist mit Sicherheit auch für Nichtprogrammierer weitgehend lesbar.
-
Und technisch / mathematisch / physikalisch dann außerdem wohl eher velocity.
-
Hallo,
du hast recht. Es heißt echt Celerity. Da hab ich mir wohl ne Vokabel falsch eingeprägt.Mit der Variablenbezeichnung gebe ich dir völlig recht. Ich werde versuchen demnächst passendere zu finden.
Sicher, mit ist klar, dass du das nicht mit Kritik meintest, sondern als Hilfestellung.
Mit 20. Jahren Programmiererfahung kann ich nicht mithalten, da ich sowieso erst 16 bin....naja aber ein Drei Viertel Jahr beschäftige ich mich nun auch schon mit C++ und versuche stetig mehr zu lernen, wie auch durch diesen Thread
Also, nochmals danke und bis bald
lg, freakC++