Seite 1 von 1

[gelöst]Grundverständnis Zeiger

Verfasst: 22. Januar 2007 20:31
von -marcelp-
Hallo,

ich schreibe eine Adressverwaltung mit zwei Fenstern. Das erste enthält eine Übersichtstabelle und auch eine Funktion zum Refresh dieser.
Das zweite Fenster wird aufgerufen, um eine Adresse anzulegen oder zu ändern und soll abschließend die Refreshfunktion aus Fenster 1 aufrufen.
Ich übergebe beim Aufruf von Fenster 2 einen Zeiger "QWidget *ptr = this". Darüber kann ich aber nur auf die Funktionen von QWidget zugreifen.
Die Refreshfunktion meiner von QWidget abgeleiteten Klasse bleibt unbekannt.

Wer löst mein (C++Anfänger-)Problem?

Marcel

Verfasst: 22. Januar 2007 21:21
von marco
Hallo,

also erstmal... am besten postest du mal ein bisschen Code. Dein Problem ist recht allgemein und etwas vage beschrieben und kann sehr viele Ursachen haben, soweit ich das überblicken kann.

Übrigens: Das was du vorhast könnte fast ein Lehrbuchbeispiel für die Verwendung von SIGNAL/SLOTS sein, das solltest du dir also mal anschauen!

Gruß, Marco

Verfasst: 22. Januar 2007 21:25
von Tarek
Hallo,
da gibt es mehrere Möglichkeiten,
  1. Typecasting bzw. das direkte Benutzen des richtigen Zeigertyps. Dazu muss allerdings dem zweiten Fenster die abgeleitete Klasse bekannt sein.
  2. Call-Back (nicht schön). Statt einem Zeiger auf das erste Fenster übergibst du einen Zeiger auf die refresh-Funktion.
  3. Signals & Slots. Du richtest die Refresh-Funktion als Slot ein und verbindest den mit einem Signal deines zweiten Fensters.

Re: Grundverständnis Zeiger

Verfasst: 23. Januar 2007 08:34
von -marcelp-
Danke erstmal für Eure Hilfe.

Also vielleicht etwas genauer:

Ich habe mit Qt's Designer in KDevelop meine beiden Formulare erstellt und davon abgeleitet. In der Klasse von Form 1 öffne ich Form 2:

void windowmain::adress_insert()
{
adressinput *ai = new adressinput(); //Aufruf Form 2
connect( ai, SIGNAL( ai.pbadrinOK->clicked() ), SLOT( this->adress_refresh() ) );
ai->show();
}

Wenn in Form 2 die Adressbearbeitung erledigt ist, soll die Refreshroutine der Tabelle in Form 1 aufgerufen werden - das passiert aber nicht.
Die connect-Zeile habe ich auf Tareks Hinweis nachträglich eingebaut, läuft so aber auch nicht.

Wenn ich das hier probiere:

void windowmain::adress_insert()
{
adressinput *ai = new adressinput( this ); //Aufruf Form 2
ai->show();
}

habe ich in

articleinput::articleinput( QWidget* ptr, const char* name, WFlags fl ): frmartikeldata(parent,name,fl)
{
}

mit *ptr den Zeiger auf die Basisklasse von Form 1, kann aber nicht auf nachträglich eingebaute Funktionen (wie eben die RefreshTable) zugreifen.

Verfasst: 23. Januar 2007 09:42
von cbrider
Also mal ein paar Sache die mir so aufgefallen sind.

1.

Code: Alles auswählen

adressinput *ai = new adressinput();
connect( ai, SIGNAL( ai.pbadrinOK->clicked() ), SLOT( this->adress_refresh() ) );
"*ai" is ja nun mal ein Pointer auf ein Objekt der Klasse adressinput und bei solchen werden Methoden und Objekte mit einem "->" angesprochen. Also solltest Du mal

Code: Alles auswählen

SIGNAL( ai->pbadrinOK.clicked() ), 
probieren.

2.
Wenn du innerhalb einer Methode ein Objekt erzeugst (hier das "*ai")

Code: Alles auswählen

void windowmain::adress_insert() 
{ 
adressinput *ai = new adressinput( this ); //Aufruf Form 2 
ai->show(); 
} 
dann gilt dieses Objekt auch nur für die Lebensdauer deiner Methode. Sprich:
- ai erzeugen
- ai->show()
- Methoden Ende
- ai ist futsch.

Besser währe so etwas

Code: Alles auswählen

class windowmain
{

  // ... der Rest deiner Klassendefinition

  private:

    adressinput *ai;
};

void windowmain::adress_insert() 
{ 
ai = new adressinput( this );
ai->show(); 
}

Dann bleibt das Objekt "*ai" über die Laufzeit der Methode "adress_insert()" hinweg gültig.

Ideal währe es auch, wenn du die Initialisierung von "*ai", also das

Code: Alles auswählen

ai = new adressinput( this );
in den Konstruktor der Klasse "windowmain" schreibst.

Hoffentlich Hilfs dir weiter

Verfasst: 23. Januar 2007 09:50
von Christian81
Das connect kann so nie funktionieren...
http://doc.trolltech.com/4.2/signalsandslots.html

Verfasst: 23. Januar 2007 10:42
von Tarek
Denke ich auch, normaler Weise müsste er da auch auf der Konsole einen Fehler anzeigen.

Also richtig wäre es wie folgt:

Code: Alles auswählen

connect(ai->pbadrinOK, SIGNAL(clicked()),this,SLOT(adress_refresh()));
Und "adress_refresh" muss natürlich als slot definiert sein.

Verfasst: 24. Januar 2007 09:22
von -marcelp-
Also erstmal Danke!

Ich habe Euren Rat befolgt, *ai ausserhalb von adress_insert() erzeugt und im Konstruktor von Form 1 die Verbindung mittels

connect( ai->pbadrinOK,SIGNAL( clicked() ),this,SLOT( adress_refresh() ) );

hergestellt.
Das hat wunderbar geklappt - genau ein mal!

Das Problem: Will ich mein Programm ausführen, öffnet sich kein Formular und in der Kontrollleiste ist kein Programm zu sehen.
Eine testhalber im Konstruktor eingefügte QMessageBox erscheint noch, nehme ich die connect-Zeile wieder raus, funktioniert alles wieder.

Liegt das überhaupt an meinem Code?

Als Info: Ich schreibe unter Kubuntu 6.06 / KDE 3.5.2 / Kdevelop 3.3.2 / Qt 3.3.6

Gruß, Marcel :(

Verfasst: 24. Januar 2007 12:46
von Tarek
Ich habe Euren Rat befolgt, *ai ausserhalb von adress_insert() erzeugt
Also darüber ob es sinnvoll ist den zweiten Dialog im Konstruktor zu erzeugen kann man sich sicher streiten, auf jeden Fall ist es so unter Umständen etwas schwieriger bei mehrfachen Aufrufen alles wieder in den gewünschten Zustand zu versetzen. Wenn du ihn hingegen in der Funktion "adress_insert()" erzeugst bekommst du immer einen "frischen" Dialog.
und im Konstruktor von Form 1 die Verbindung mittels

connect( ai->pbadrinOK,SIGNAL( clicked() ),this,SLOT( adress_refresh() ) );

hergestellt.
Das hat wunderbar geklappt - genau ein mal!

Das Problem: Will ich mein Programm ausführen, öffnet sich kein Formular und in der Kontrollleiste ist kein Programm zu sehen.
Eine testhalber im Konstruktor eingefügte QMessageBox erscheint noch, nehme ich die connect-Zeile wieder raus, funktioniert alles wieder.
Wäre sehr sinnvoll wenn du den Code wie er jetzt ist und den debugger output / backtrace posten würdest. So kann man nur raten...
Hast du vielleicht das connect() vor der Erzeugung des Dialogs aufgerufen?

Verfasst: 25. Januar 2007 08:24
von -marcelp-
Danke Euch allen, jetzt läuft alles wie gewünscht.
Ich habe die connect-Zeilen im Konstruktor von Form 1 erstellt, ist natürlich Blödsinn.

Tarek, sage mir bei Gelegenheit mal, was Du gerne trinkst...

Gruß, Marcel :D