Seite 1 von 1

QMessageBox Modalitaet und Speicherverwaltung

Verfasst: 15. April 2008 17:26
von ColonelMoW
Hi,
ich habe eine Frage zu Modalitaet und Speicherverhalten von QMessageBox.
(QT Version 4.x)

QMessageBox erzeugt mir eine modale Nachrichtenbox. Modal heisst, dass ich
sie erst wegklicken muss, bevor ich mit dem Widget weiterarbeiten kann,
zu dem sie modal ist.

Unterschiede zwischen exec() und show() bei QMessageBox:
exec() wuerde ja fuer die MessageBox eine eigene Event-Loop anlegen.
Sprich das Programm bleibt solange an der Stelle stehen, bis die
Nachrichtenbox weggedrueckt wird.
bei show() laeuft die Anwendung im Hintergrund weiter. (Ich kann
nur eben das Widget, zu dem die Box modal ist nicht anwaehlen)
Ist das soweit korrekt?

Das Widget zu dem eine QMessageBox modal sein soll uebergibt man ihr als
parent im Konstruktor.

Nur wo bleibst da jetzt der Pltatz fuer die Speicherverwaltung?
Normalerweise wird ja ein Widget geloescht, wenn....
....es auf dem Heap liegt und sein parent geloescht wird
....es auf dem Heap liegt und ich es mit delete loesche (dann darf es
kein Parent haben!)
....es auf dem Heap liegt, ein Parent hat und ich explizit deleteLater()
aufrufe
....es auf dem Stack liegt und die Funktion, in der es angelegt wurde
verlassen wird (dann darf es auch kein Parent haben - muss also root sein).

Wann wird jetzt aber eine MessageBox geloescht? Das Parent wird ja hier
etwas zweckentfremdet. Oder gelten hier weiterhin die oben genannten Regeln?
Wie kann ich dann eine MessageBox erzeugen, die Modal zur gesamten
Anwendung ist (also eigentlich Parent = 0), und trotzdem ein Parent
im oben genannten Sinn (Speicherverwaltung) hat?

Und wo liegen eigentlich die MessageBoxen von den statischen Memberfunktionen:
z.B.: QMessageBox::critical(....) ?
Auf dem Stack oder auf dem Heap?

Ich wuerde mich sehr freuen, wenn mir jemand helfen kann.
Falls ich mich nicht verstaendlich genug ausgedrueckt habe, bitte kurzer Hinweis.

Col

Verfasst: 16. April 2008 07:16
von macman
Langeweile gehabt? :-) Eine MessageBox ist ein Dialog wie jeder andere auch.

Verfasst: 16. April 2008 08:16
von RHBaum
...es auf dem Heap liegt und ich es mit delete loesche (dann darf es
kein Parent haben!)
sicher ? normal kannst es per delete loeschen ... im destruktur sollt es sich vorher aus allen QT hirarchien ausklinken ....

Funktioniert das bei dir nicht ?
Und wo liegen eigentlich die MessageBoxen von den statischen Memberfunktionen:
z.B.: QMessageBox::critical(....) ?
Wahrscheinlich lokal in der critical funktion .... schau dir den quellcode an !
Oder hasst es schon mal geschafft , aus der critical funktion rauszukommen bevor das fenster geschlossen wurde ? :-)

Ciao ....

Verfasst: 16. April 2008 08:59
von ColonelMoW
RHBaum hat geschrieben:
...es auf dem Heap liegt und ich es mit delete loesche (dann darf es
kein Parent haben!)
sicher ? normal kannst es per delete loeschen ... im destruktur sollt es sich vorher aus allen QT hirarchien ausklinken ....

Funktioniert das bei dir nicht ?
Ich habe es nicht probiert, aber ich habe gelesen, dass man das nicht tun sollte. Wenn die Anwendung geschlossen wird, und damit die root vernichtet wird, geht die Speicherverwaltung von QT durch und loescht alle Kinder. Wenn man ein Kind nun schon vorher per delete loescht, ist es als ob man bereits freigegebenen Speicher am Ende nochmal freigeben moechte.
Oder meinst du, dass man im Destruktor des Kindes das selbige quasi unabhaengig macht? Also ueber setParent(NULL)? Dann geht es natuerlich. Dann hat es ja auch kein Parent mehr... oder?
RHBaum hat geschrieben:
Und wo liegen eigentlich die MessageBoxen von den statischen Memberfunktionen:
z.B.: QMessageBox::critical(....) ?
Wahrscheinlich lokal in der critical funktion .... schau dir den quellcode an !
Oder hasst es schon mal geschafft , aus der critical funktion rauszukommen bevor das fenster geschlossen wurde ? :-)

Ciao ....
Heisst das dann, dass die MessageBox hier auf dem Stack liegt? Es wird quasi in der statischen Funktion critical() ein Dialog erstellt. Wenn die Funktion critical() verlassen wird (also wenn man z.B. den okay-Button in der Box drueckt), wird der Speicher der DialogBox sofort wieder freigegeben und es bleibt nur der Rueckgabewert uebrig. Richtig?

Verfasst: 16. April 2008 09:10
von Christian81
ColonelMoW hat geschrieben: Ich habe es nicht probiert, aber ich habe gelesen, dass man das nicht tun sollte. Wenn die Anwendung geschlossen wird, und damit die root vernichtet wird, geht die Speicherverwaltung von QT durch und loescht alle Kinder. Wenn man ein Kind nun schon vorher per delete loescht, ist es als ob man bereits freigegebenen Speicher am Ende nochmal freigeben moechte.
Im Grunde korrekt. Wenn ich aber ein Kind lösche ist es weg und demnach hat der Parent auch keinen Zugriff auf das Child mehr. Es gibt nur wenige Fälle wo man deleteLater() wirklich benutzen muss.
ColonelMoW hat geschrieben: Heisst das dann, dass die MessageBox hier auf dem Stack liegt? Es wird quasi in der statischen Funktion critical() ein Dialog erstellt. Wenn die Funktion critical() verlassen wird (also wenn man z.B. den okay-Button in der Box drueckt), wird der Speicher der DialogBox sofort wieder freigegeben und es bleibt nur der Rueckgabewert uebrig. Richtig?
Wo sie liegt wissen wir erstens nicht und zweitens kann es uns egal sein - wenn eine (statische) Funktion Speicher anfordert sollte sie sich auch drum kümmern daß wieder aufgeräumt wird.

Verfasst: 17. April 2008 09:24
von ColonelMoW
Danke euch. Ihr habt mir sehr weitergeholfen!

Verfasst: 17. April 2008 13:13
von gerome69
Christian81 hat geschrieben:Es gibt nur wenige Fälle wo man deleteLater() wirklich benutzen muss.
Die da wären? Da ich immer an sauberen Code interessiert bin, der den benutzen Speicher hinterher auch wieder freigibt, hätte ich das gerne mal gewußt.

Gruß, Gérôme

Verfasst: 17. April 2008 13:23
von Christian81
Wenn man z.B, ein QObject in einem Slot löscht und deshalb ggf. noch Events, die auf das QObject referenzieren, in der Queue sind.

Verfasst: 17. April 2008 14:06
von gerome69
Christian81 hat geschrieben:Wenn man z.B, ein QObject in einem Slot löscht und deshalb ggf. noch Events, die auf das QObject referenzieren, in der Queue sind.
Danke. Das ist ne klare Ansage.

Ich habe dem ganzen bisher nie so recht vertraut und Objekte immer selbstständig instanziert und im Destruktor gelöscht, obwohl mir schon klar war, daß letzteres wahrscheinlich überflüssig ist.

ZB:

Code: Alles auswählen

// Header
class MainWindow: public QMainWindow {
    public:
        MainWindow();
        ~MainWindow();

    private:
         QPushButton *myButton;
}

// Implementierung
// Im Konstruktor zB.
MainWindow::MainWindow() {
    myButton=new QPushButton();
}

// Und im Destruktor zB:

MainWindow::~MainWindow() {
    delete myButton;
}
Bei vielen (grafischen) Elementen etwas mühselig, da den Überblick zu behalten.

G.

Verfasst: 17. April 2008 17:46
von ColonelMoW
@gerome69,

bei deinem Beispiel haettest du dem Button einfach das MainWindow objekt (also this) als Parent geben koennen. Dann wird dein Button ganz automatisch geloescht, wenn die MainWindow Instanz geloescht wird.

Ich lege z.B. die Root auf den Stack und alle anderen Objekte sind dann Kinder und Kindes-Kinder,.... . Das hat dann beim Schliessen der Anwendung den Domino-Effekt, dass erstmal aufgeraeumt wird.

Col