QMessageBox Modalitaet und Speicherverwaltung

Alles rund um die Programmierung mit Qt
Antworten
ColonelMoW
Beiträge: 30
Registriert: 15. April 2008 16:24

QMessageBox Modalitaet und Speicherverwaltung

Beitrag 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
macman
Beiträge: 1738
Registriert: 15. Juni 2005 13:33
Wohnort: Gütersloh
Kontaktdaten:

Beitrag von macman »

Langeweile gehabt? :-) Eine MessageBox ist ein Dialog wie jeder andere auch.
Die deutsche Schriftsprache ist case-sensitive. Außerdem gibt es eine Interpunktionsnorm. Wenn manch einer seine Programme genauso schlampig schreibt, wie sein Posting hier, dann sollte er es lieber bleiben lassen.
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag 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 ....
ColonelMoW
Beiträge: 30
Registriert: 15. April 2008 16:24

Beitrag 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?
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag 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.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
ColonelMoW
Beiträge: 30
Registriert: 15. April 2008 16:24

Beitrag von ColonelMoW »

Danke euch. Ihr habt mir sehr weitergeholfen!
gerome69
Beiträge: 188
Registriert: 28. April 2006 22:50
Wohnort: Berlin
Kontaktdaten:

Beitrag 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
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag 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.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
gerome69
Beiträge: 188
Registriert: 28. April 2006 22:50
Wohnort: Berlin
Kontaktdaten:

Beitrag 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.
ColonelMoW
Beiträge: 30
Registriert: 15. April 2008 16:24

Beitrag 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
Antworten