QT initiale Fensterposition nach show()



  • Hallo zusammen

    ich erzeuge ein QMainWindow und möchte dessen (korrekte) initiale Position ermitteln und abspeichern.

    Dazu habe ich die drei Events showEvent(...), resizeEvent(...) und moveEvent(...) überladen, unter der Annahme das irgendwo dort die tatsächliche Fenster Position verfübar ist.

        void QMagicWindow::showEvent( QShowEvent *event )
        {
            QMainWindow::showEvent( event );
            qDebug() << "QMagicWindow::showEvent" << "frameGeometry():" << frameGeometry();
        }
    
    
        void QMagicWindow::moveEvent( QMoveEvent *event )
        {
            QMainWindow::moveEvent( event );
            qDebug() << "QMagicWindow::moveEvent" << WindowType << "frameGeometry():" << frameGeometry();
        }
    
    
        void QMagicWindow::resizeEvent( QResizeEvent *event )
        {
            QMainWindow::resizeEvent( event );
            qDebug() << "QMagicWindow::resizeEvent" << WindowType << "frameGeometry():" << frameGeometry();
        }
    
    

    Der Output ist folgender:

    QMagicWindow::moveEvent "MAIN" frameGeometry(): QRect(-8,-30 216x138)
    QMagicWindow::resizeEvent "MAIN" frameGeometry(): QRect(-8,-30 216x138)
    QMagicWindow::showEvent frameGeometry(): QRect(-8,-30 216x138)

    Die Position ist in allen drei Events bei (-8, 30). Was nicht korrekt ist, da das Fenster so ziemlich in der Mitte meines Bildschirms entsteht und nach minimalem verschieben plötzlich Koordinaten im Bereich von 600,400 anzeigt, was mehr Sinn macht.

    Nach dem show()-Aufruf in main.cpp sieht "frameGeometry()" übrigens so aus:
    main() QRect(632,250 216x138)*
    Das nützt mir aber nix, weil das schon zu spät ist. Ich will es durch Events in der Window-Klasse ermitteln.

    Die asynchrone Lösung ist sowas hier:

    void MyApp::showEvent(QShowEvent *event) {
        QMainWindow::showEvent(event);
        QTimer::singleShot(50, this, SLOT(window_shown()));
        return;
    }
    

    Aber ich suche eine elegante Lösung ohne Timer-Gewurschtel.

    Fällt euch da was ein?





  • @Sillo sagte in QT initiale Fensterposition nach show():

    http://doc.qt.io/archives/qt-4.8/qwidget.html#saveGeometry

    Das ist mir bekannt. Kriegt man das QByteArray, was 'saveGeometry' zurückliefert irgendwie auseinander klamüsert?

    SaveGeometry war nämlich mein erster Ansatz, aber wenn man das mit dem QXmlStreamWriter in eine XML-Datei schreiben will, kommt von dem Byte-Datenstrom nicht viel dort an. Daher habe ich die Variante erstmal verworfen. Abgesehen davon ist das natürlich in egal welcher Art von Konfigurationsdatei nicht lesbar.

    Wenn man das mit QSettings::setValue() speichert sieht das übrigens so aus:

    @ByteArray(\x1\xd9\xd0\xcb\0\x2\0\0\xff\xff\xf9\xf2\0\0\0r\xff\xff\xfb\x91\0\0\x3\x34\xff\xff\xf9\xfa\0\0\0\x90\xff\xff\xfb\x89\0\0\x3,\0\0\0\x1\0\0\0\0\a\x80)

    Nicht unbedingt ne schöne Konfigurationsdatei....



  • Ja. Du kannst dir die einzelnen Byte ansehen bzw. einzeln speichern. Welche Reihenfolge die Bytes haben wirst du ja herausfinden.
    http://doc.qt.io/qt-5/application-windows.html#window-geometry



  • Habe eine elegantere Variante gefunden:

    Das Event "QEvent::ShowToParent" ist ein Event was kurz nach dem ShowEvent aufgerufen wird und es ist das erste Event, in dem die Werte von "frameGeometry" korrekt sind.
    Man muss dafür lediglich die virtuelle Funktion "virtual bool event( QEvent* ) override;" überladen und den entsprechenden Eventtyp abfangen.

        bool QMagicWindow::event( QEvent *event )
        {
            QMainWindow::event( event );
            if ( event->type() == QEvent::ShowToParent )
            {
                // Speichern die initiale Position
                if ( Cfg.setGeometry( frameGeometry() ) )
                {
    
                }
            }
            return true;
        }
    


  • @It0101 sagte in QT initiale Fensterposition nach show():

    @Sillo sagte in QT initiale Fensterposition nach show():

    http://doc.qt.io/archives/qt-4.8/qwidget.html#saveGeometry

    Das ist mir bekannt. Kriegt man das QByteArray, was 'saveGeometry' zurückliefert irgendwie auseinander klamüsert?

    SaveGeometry war nämlich mein erster Ansatz, aber wenn man das mit dem QXmlStreamWriter in eine XML-Datei schreiben will, kommt von dem Byte-Datenstrom nicht viel dort an. Daher habe ich die Variante erstmal verworfen. Abgesehen davon ist das natürlich in egal welcher Art von Konfigurationsdatei nicht lesbar.

    Wenn man das mit QSettings::setValue() speichert sieht das übrigens so aus:

    @ByteArray(\x1\xd9\xd0\xcb\0\x2\0\0\xff\xff\xf9\xf2\0\0\0r\xff\xff\xfb\x91\0\0\x3\x34\xff\xff\xf9\xfa\0\0\0\x90\xff\xff\xfb\x89\0\0\x3,\0\0\0\x1\0\0\0\0\a\x80)

    Nicht unbedingt ne schöne Konfigurationsdatei....

    Dafür ist das ganze auch nicht gedacht, damit ein Mensch da was rumschrauben soll. Die Frage ist muss der Nutzer deines Programms im settings file an der geometry änderungen vornehmen können?



  • @firefly sagte in QT initiale Fensterposition nach show():

    Dafür ist das ganze auch nicht gedacht, damit ein Mensch da was rumschrauben soll. Die Frage ist muss der Nutzer deines Programms im settings file an der geometry änderungen vornehmen können?

    Nee prinzipiell nicht. Zu Debugzwecken schadet es aber nicht, wenn sowas lesbar niedergeschrieben ist.
    Mich wundert einfach dass QT außer mit "saveGeometry" keinen gescheiten Weg anbietet, wie man nach dem initialen "move" die echten Koordinaten rausfinden kann. Die einzige Variante ist ein kryptisch encodetes ByteArray und die QRect-liefernden Funktionen treffen Falschaussagen.

    Abgesehen von der Lösung, die ich gefunden haben, die aber auch ein Umweg ist.



  • Weiß jetzt nicht genau, was dein Problem ist. Debug doch einfach in saveGeometry rein, dann siehst du, was da intern aufgerufen wird (vermutlich geomeotry()). Das kannst du dann auch selber aufrufen und mit den vier Werten machen, was du willst.



  • @Mechanics
    Ich hab doch meine passende Lösung schon gefunden 😉