zugriff auf dynamisch erstellten button von außen?



  • DarkBug schrieb:

    kommt einfach die Fehlermeldung, das das Object nicht existiert

    Die Fehlermeldung bringt dir nichts? Und poste nächstes Mal lieber die wörtliche als die interpretierte Fassung. 😉

    DarkBug schrieb:

    kommt die Fehlermeldung, das Test kein Element von TForm1 ist.

    Aber Test ist tatsächlich ein Member von TForm1 ?



  • Ich habe jedenfalls den Button im Konstuktor von TForm1 erstellt:

    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
    TButton *Test = new TButton(this);
    Test->Parent = this;
    Test->Name = "Test";
    Test->Caption = "Test";
    Test->Left = 32;
    Test->Top = 16;
    Test->Width = 145;
    Test->Height = 121;
    Test->OnClick = TestClick;
    }
    

    Im Prinzip erstelle ich doch einen neuen Button der Klasse TButton in der Klasse TForm1 oder sehe ich das falsch? Ich verstehe das noch nicht so ganz. Stimmt die Deklarierung denn so?

    TButton *Test = new TButton(this);
    


  • Du erstellst deinen Button lokal im Konstruktor deiner Form. So ist er natürlich nach außen nicht bekannt. Mach den Button Test zum Member deiner Form.



  • Nein, du erstellst eine lokale Variable, diese ist nach dem Konstruktor nicht mehr sichtbar. Du musst Test als Membervariable in der Klasse TForm1 deklarieren.



  • Das heißt ich soll den Button in der Klasse TForm1 im Header erstellen? Dann kommt eine Fehlermeldung:

    Klassenelement kann hier nicht initialisiert werden.



  • Du sollst ihn dort nur deklarieren. Erstellen kannst du nach wie vor im Konstruktor.



  • Das hatte ich am Anfang so, ich kann dann zwar auf den Button extern zugreifen, jedoch bekomme ich dann für jeden Button beim starten eine Fehlermeldung:

    Feld Form1->Test besitzt keine entsprechende Komponente. Soll die Deklaration entfernt werden?

    Er startet das Programm zwar trotzdem, aber das kann doch so nicht richtig sein.



  • Dann hast du deinen Button wohl über den Objektinspektor eingefügt und dann den Button selbst aus der Form gelöscht? Dann meckert der Builder natürlich.
    Du musst die Membervariable per Hand in den public:-Teil deiner Form einfügen.
    etwa so

    class TForm1 : public TForm {
    __published:	// Von der IDE verwaltete Komponenten
    private:	// Anwender-Deklarationen
    public:		// Anwender-Deklarationen
      TButton* Test;
        __fastcall TForm1 (TComponent* Owner);
    };
    

    und dann im Konstruktor

    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
      Test = new TButton(this);
      Test->Parent = this;
    ...
    }
    


  • Zur Laufzeit? Hmm... Ich fürchte, das hat dann nicht mehr viel mit C++ zu tun.

    In diesem Sinne: Kann ein Moderator diesen Thread ins VCL-Forum verschieben?



  • Stimmt. Das wird langsam fällig. 🙂



  • Ich habe alles manuell eingefügt und nicht über irgenteinen Objektinspector. Hatte den Button zuerst unter public deklariert, jedoch kommt, wenn ich dann auf den Button klicke, der den Dynamischen Button sichtbar machen soll eine Zugriffsverletzung. Dann habe ich mich an den statischen Buttons orientiert und den Button unter published deklariert, aber dort kommt die andere Fehlermeldung.



  • DarkBug schrieb:

    Ich habe alles manuell eingefügt und nicht über irgenteinen Objektinspector. Hatte den Button zuerst unter public deklariert, jedoch kommt, wenn ich dann auf den Button klicke, der den Dynamischen Button sichtbar machen soll eine Zugriffsverletzung.

    Das liegt jetzt aber nicht an der Position im Header, sondern höchstwahrscheinlich an der Art und Weise, wie du deinen Button im Konstruktor initialisieren wolltest. Hast du mal deine und meine Konstruktorversion verglichen?
    Ich sagen nur mal wieder "lokale Variable"
    Ansonsten gibt es für diese Art von Fehlern einen Debugger, mit dem man Alles schön überprüfen kann.

    DarkBug schrieb:

    Dann habe ich mich an den statischen Buttons orientiert und den Button unter published deklariert, aber dort kommt die andere Fehlermeldung.

    Eine selbst erstellte Membervariable hat dort nichts zu suchen.



  • Das liegt jetzt aber nicht an der Position im Header, sondern höchstwahrscheinlich an der Art und Weise, wie du deinen Button im Konstruktor initialisieren wolltest. Hast du mal deine und meine Konstruktorversion verglichen?
    Ich sagen nur mal wieder "lokale Variable"
    Ansonsten gibt es für diese Art von Fehlern einen Debugger, mit dem man Alles schön überprüfen kann.

    Also war mein Button doch falsch initialisiert. Habs geändert und nun funktioniert er wie er soll. Welchen Debugger benutzt du denn?

    Eine selbst erstellte Membervariable hat dort nichts zu suchen.

    Ja, hätt ich selbst drauf kommen können, steht ja sogar dabei >.<.

    __published: // Von der IDE verwaltete Komponenten

    Könntet ihr mir vielleicht noch sagen wie ich den Destruktor von TForm1 initialisieren kann? Auf die übliche Weiße funktioniert das irgentwie nicht oder ich stell mich wieder zu blöd an >.<.
    Den Destruktor möchte ich wie es normal ist dazu benutzen den Button wieder zu deleten:

    if(Test)
    {
    delete Test;
    }
    

    Könntet ihr mir erklären wozu das eigentlich gut ist? Denn es funktioniert doch auch alles so.



  • DarkBug schrieb:

    Welchen Debugger benutzt du denn?

    Den im BCB eingebauten.
    http://www.junix.ch/bcb/help/debug.html
    Zum Destruktor.
    Den Destruktor einer Form musst du selber erstellen. Der würde etwa so aussehen.

    __fastcall TForm1::~TForm1()
    {
    ...
    }
    

    Die Deklaration muss noch in den public-Teil, am besten gleich unter den Konstruktor.
    Wenn du deinen Button aber so erzeugst.

    Test = new TButton(this);
    

    dann brauchst eigentlich kein delete. Das this, was du da im Konstruktor von TButton mitgegeben hast, ist der Owner der Komponente (des Buttons). Der ist auch für das Löschen zuständig. In diesem Fall bedeutet das, dass die Form selbst schon das Löschen übernimmt.
    Nur wenn du dort 0 statt this hinschreibst, musst du das löschen selbst übernehmen.



  • Zum Destruktor:
    Ja, genau das habe ich auch gemacht. Bei meinen eigenen Klassen funktioniert das auch immer wunderbar, jedoch gibt es bei den Klassen von Borland immer Schwierigkeiten.

    Hier meine cpp:

    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    __fastcall TForm1::~TForm1(TComponent* Owner)
            : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    

    Hier mein Header:

    public:		// Anwender-Deklarationen
            __fastcall TForm1(TComponent* Owner);
            __fastcall ~TForm1(TComponent* Owner);
    

    Hier der Fehler:

    In Klassen im VCL-Stil definierte Destruktoren müssen virtuell sein.
    

    Zum Button:
    Danke, gut zu wissen das ich kein delete brauche. Im Prinzip brauche ich folgenden Code dann doch auch eigentlich gar nicht oder?

    Test->Parent = this;
    

    Weil der Parent in den Runden Klammern hier

    Test = new TButton(this);
    

    schon angegeben wird, oder?



  • Jetzt was zu deinen Fragen.
    1. Dein Destruktor ist falsch. Der hat weder Argumente noch braucht er eine Initialisierungsliste. Sieh einfach nochmal genauer mein Beispiel an.

    2. Das was du beim Konstruktor deiner Komponente mitgibst ist der Owner, ist für das Löschen zuständig, und nicht der Parent. Der Parent ist die Komponente auf dem deine Komponente (Button) dargestellt wird.
    Du brauchst also beides.


Anmelden zum Antworten