Seite 1 von 1

Fenster zentrieren nach resizeEvent unter Windows

Verfasst: 8. Dezember 2009 18:51
von hakaishi
Hallo Miteinander,
Unter Windows funktioniert mein resizeEvent nicht richtig. Beim vergrößern des Fensters bleibt die alte größe erhalten.
Ich möchte, dass das Fenster bei einem resize wieder zentriert wird. Dies mache ich am Ende mit move(), was jedoch das Verändern der Fenstergröße verhindert, aber warum, und was kann ich dagegen tun?

Gruß, Hakaishi

Verfasst: 8. Dezember 2009 19:22
von upsala
Was soll denn das Speicherleck an dieser Stelle?

Ich nehms zurück: Das Programm ist voll mit Speicherlecks...

Außer, daß event. das move(...) dazwischenfunkt, seh ich keinen Grund, warum das resizeEvent nicht funktionieren soll.

Verfasst: 8. Dezember 2009 23:16
von hakaishi
Hi! Das mit den Speicherlecks habe ich noch nicht ganz begriffen...
Kannst du mir eine Stelle in meinem Programm zeigen und mir sagen, wie ich das behebe?

Gruß, Hakaishi

Verfasst: 9. Dezember 2009 08:30
von franzf
hakaishi hat geschrieben:Hi! Das mit den Speicherlecks habe ich noch nicht ganz begriffen...
Kannst du mir eine Stelle in meinem Programm zeigen und mir sagen, wie ich das behebe?

Code: Alles auswählen

pos = new QPoint((desktop->width() - frameGeometry().width()) / 2,
                     (desktop->height() - frameGeometry().height()) / 2);
An der Stelle erzeugst du ein Objekt mit new. Solche Objekte müssen immer von Hand wieder mit delete über den Jordan geschickt werden. Das geschieht bei dir nicht.
pos ist zwar ein Member deiner Klasse. Nach obiger Zeile ist aber das alte Objekt nicht mehr erreichbar und somit nicht mehr löschbar, es dümpelt irgendwo im Speicher rum bis nach Programmende das OS den Speicher säubert.
Da ein resizeEvent() ziemlich oft aufgerufen wird, fällt das besonders ins Gewicht. In dem Fall ist es vor allem unnötig, pos als Member zu deklarieren, und dann auch noch als Pointer! pos ist eine Variable die nur in resizeEvent() für das move() gebraucht wird, so was hat nichts bei den Membervariablen zu suchen!
Insvesondere ist das Konstruieren eine QPoint-Objekts an der STelle unnötig, da es noch eine zweite für dich geeignetere Variante von move() gibt!

Und jetzt schau dir das closeEvent() an, da solltest du zwei potentielle Lecks entdecken. Es ist zwar das Letzte, was dein Programm macht, aber trotzdem.
Allerdings ist das vom Programmiertechnischen doof, das ins closeEvent() zu legen. Das ist typische Destruktorarbeit!
Wobei du auch beachten solltest, dass dein Settings-Objekt nie zerstört wird, und damit auch nie Settings geschrieben werden (hast du dich da noch gar nicht gewundert?) Du brauchst settings nicht als Member, und auch nicht als Pointer!

Das "saubere Beenden" durch den Destruktor kannst du dir auch irgendwo schenkden... Der shutdown schickt allen Programmen das SIGTERM, wenn sie nicht schließen wollen ein SIGKILL (für SIGTERM musst du einen Signal-Handler installieren, SIGKILL kannst du nicht abfangen), da gibt es eh keinen ordnungsgemäßen Destruktor mehr. Wenn du die Settings speichern willst, mach das in einer Methode saveSettings(), die du direkt aufrufst. Es ist dir bei einem shutdown nämlich nicht garantiert, dass dein Programm noch in die nächste Runde der EventLoop kommt, wo dann im closeEvent() die Settings "gespeichert" werden (werden sie ja eh bei dir nicht :P).

Du solltest vertieft die Programme aus den Examples anschauen. Bei dir herrscht bei der Programmkonzeption noch ziemliches Chaos ;)

Verfasst: 9. Dezember 2009 10:08
von hakaishi
Sorry, sieht ganz so aus, als hätte ich den ganzen Mist gestern da reingebaut...
Ich habe hier eine verbesserte Version. Wenn es sonst noch was ist,.. *please tell me*

Gruß, Hakaishi

Verfasst: 9. Dezember 2009 21:09
von hakaishi
Hey, ich habe eine Lösung, aber wie ich finde, keine sehr gute:

Code: Alles auswählen

gui.h

...
bool hasBeenResized;

Code: Alles auswählen

gui.cpp

void Gui::update(){
    if(hasBeenResized){
      QDesktopWidget *desktop = qApp->desktop();
      QPoint pos((desktop->width() - frameGeometry().width()) / 2,
                 (desktop->height() - frameGeometry().height()) / 2);
      move(pos);
    }
...
}
...
void Gui::resizeEvent(QResizeEvent* window_resize){
    hasBeenResized = true;
    QWidget::resizeEvent(window_resize);
}
Nachteil: das Fenster wird erst 1 Sekunde nach dem resizeEvent zentriert und zusätzlich noch erst nach dem betätigen des OK-Buttons...

Hat jemand eine bessere Idee?

Verfasst: 10. Dezember 2009 17:53
von hakaishi
Hat denn keiner eine Idee? :( :?:

Verfasst: 10. Dezember 2009 18:44
von upsala
Warum willst du das Fenster mit aller Gewalt zentrieren?
Wo soll denn die 1 Sekunde herkommen, das ist aus dem Code nicht ersichtlich.

Verfasst: 10. Dezember 2009 19:00
von hakaishi
upsala hat geschrieben:Warum willst du das Fenster mit aller Gewalt zentrieren?
Wo soll denn die 1 Sekunde herkommen, das ist aus dem Code nicht ersichtlich.
Sorry, stimmt. Die Funktion void Gui::update() wird durch einen timeout()-SLOT eines QTimers jede Sekunde aufgerufen. Allerdings beginnt dieser Timer erst nach dem drücken des OK-Buttons.

Ich finde, dass es besser ist, wenn das Fenster immer zentriert ist...
Eigentlich benutze ich ja eh Linux und es kann mir egal sein, was unter Windows passiert... Vorübergehend habe ich es einfach so gemacht:

Code: Alles auswählen

void Gui::resizeEvent(QResizeEvent* window_resize){
#ifndef Q_OS_WIN32
    QDesktopWidget *desktop = qApp->desktop();
    QPoint pos((desktop->width() - frameGeometry().width()) / 2,
               (desktop->height() - frameGeometry().height()) / 2);
    move(pos);
#endif
    QWidget::resizeEvent(window_resize);
}
Aber da ich ja Plattformunabhängig sein will, müsste da für Windows eben auch was rein, funktioniert wegen move() aber nicht. Also was tun?

Gruß, Hakaishi

Verfasst: 13. Dezember 2009 17:36
von hakaishi
Also... Ich bin da auf etwas gestoßen: Wenn man unter Linux einen resize macht und das resizeEvent so aussieht:

Code: Alles auswählen

gui.cpp

void Gui::resizeEvent(QResizeEvent* window_resize){
    qDebug()<<"hallo";
    QWidget::resizeEvent(window_resize);
}
dann wird beim Programmstart einmal und nach jedem weiteren resize ein weiteres "hallo" ausgegeben. Unter Windows dagegen wird beim Programmstart zwar auch einmal "hallo" ausgegeben, aber beim größer Ziehen des Fensters nicht nur einmal (danach), sondern solange bis die man den Mauszeiger wieder los lässt.

Ich habe nun versucht, eine bool-Variable beim resizeEvent true zu setzten, und dann ein SIGNAL emit isResized(); auszugeben, welches dann in der Klasse Gui mit connect(this, SIGNAL(isResized()), this, SLOT(center())); das Fenter wieder zentrieren soll. Hierzu habe ich noch die Funktion center() angelegt:

Code: Alles auswählen

gui.cpp
void Gui::center(){
    QDesktopWidget *desktop = qApp->desktop();
    QPoint pos((desktop->width() - frameGeometry().width()) / 2,
               (desktop->height() - frameGeometry().height()) / 2);
    move(pos);
    hasBeenResized = false;
}
aber auch dieser Umweg hat nichts genützt.

Hat jemand nicht doch noch eine Idee (oder weiß wie es geht)?

Gruß, Hakaishi

Verfasst: 13. Dezember 2009 17:42
von upsala
Note that the desktop may be composed of multiple screens, so it would be incorrect, for example, to attempt to center some widget in the desktop's geometry.

Verfasst: 13. Dezember 2009 17:46
von hakaishi
upsala hat geschrieben:
Note that the desktop may be composed of multiple screens, so it would be incorrect, for example, to attempt to center some widget in the desktop's geometry.
aha... und was soll ich dann unter Windows anders machen? (unter Win XP habe ich nur einen Bildschirm bzw. eine Arbeitsfläche, im Gegensatz zu Linux....)
PS: Wo hast du das Zitat her?