How can I send parent to a new ApplicationWindow

313 views Asked by At

I want to recover the position and the size of the master "main.qml". But I do not know how to declare the parent of the new window. I have no problem if I open the window directly from the window main.qml in javascript but through python I do not see how.

I think I have to use "self.win" but how declare it ?

Thanks for yours responses.

test.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQml import QQmlApplicationEngine
from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot
import sys

class Main2(QObject):

    def __init__(self, engine, what_send_for_send_the_parent):
        QObject.__init__(self)

        """ 
        How can I say to the new windows who is the parent  ?
        """
        context = engine.rootContext()
        context.setContextProperty("py_Page2", self)
        engine.load('test2.qml')
        self.win = engine.rootObjects()[0]  

class Main(QObject):

    def __init__(self, engine):
        QObject.__init__(self)

        self.context = engine.rootContext()
        self.property = self.context.setContextProperty("py_Page", self)
        self.load = engine.load('test.qml')
        self.win = engine.rootObjects()[0]  

        print("Context", self.context)  # <PyQt5.QtQml.QQmlContext object at 0xb65e6f30>
        print("Property", self.property)# None
        print("Load", self.property)    # None
        print("Win", self.win)          # <PyQt5.QtGui.QWindow object at 0xb65e6f80>

if __name__ == "__main__":
    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()

    main = Main(engine) 
    main2 = Main2(engine, "???")

    engine.quit.connect(app.quit)
    sys.exit(app.exec_())

test.qml

import QtQuick 2.5
import QtQuick.Controls 1.4

ApplicationWindow {
    id: "main"
    visible: true
    width: 200; height: 240;    
    Text {text: qsTr("main")} 
}

test2.qml

import QtQuick 2.5
import QtQuick.Controls 1.4

ApplicationWindow {
    id: "main2"
    visible: true
    width: 200; height: 240;
    x: main.x
    y: main.y
    Text {text: qsTr("main2")}
}

I think I have found :

class Main2(QObject):

    def __init__(self, engine, master):
        QObject.__init__(self)
        context = engine.rootContext()
        context.setContextProperty("main_x", master.win.property("x"))
        context.setContextProperty("main_y", master.win.property("y"))
        engine.load('test2.qml')

...
    main = Main(engine) 
    main2 = Main2(engine, main)
...

And in the file qml

ApplicationWindow {
    id: "main2"
    visible: true
    width: 200; height: 240;
    x: main_x + 20
    y: main_y + 120
    Text {text: qsTr("main2")}
}

I can recover the value like that. Is this correct? Is there a more conventional way?

1

There are 1 answers

3
eyllanesc On BEST ANSWER

Although the solution works in this case it can fail in more real cases where each QML can load many components since the QML load is asynchronous but your procedure is synchronous.

The solution is to create a QObject and export it to QML using setContextProperty() so that it is accessible from all the QMLs that are loaded through the QQmlApplicationEngine. That QObject must have a property that is a mirror of the property you want to obtain.

main.py

from PyQt5.QtCore import pyqtProperty, pyqtSignal, QObject, QPoint, QUrl
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQml import QQmlApplicationEngine


class Manager(QObject):
    positionChanged = pyqtSignal()

    def __init__(self, parent=None):
        super().__init__(parent)
        self._position = QPoint()

    @pyqtProperty(QPoint, notify=positionChanged)
    def position(self):
        return self._position

    @position.setter
    def position(self, p):
        if self._position != p:
            self._position = p
            self.positionChanged.emit()


if __name__ == "__main__":
    import os
    import sys

    app = QGuiApplication(sys.argv)

    engine = QQmlApplicationEngine()
    manager = Manager()
    engine.rootContext().setContextProperty("manager", manager)

    current_dir = os.path.dirname(os.path.realpath(__file__))

    engine.load(QUrl.fromLocalFile(os.path.join("test.qml")))
    engine.load(QUrl.fromLocalFile(os.path.join("test2.qml")))

    engine.quit.connect(app.quit)
    sys.exit(app.exec_())

test.qml

import QtQuick 2.5
import QtQuick.Controls 1.4

ApplicationWindow {
    id: root
    visible: true
    width: 200
    height: 240
    Text {
        text: qsTr("main")
    }
    Component.onCompleted: manager.position = Qt.point(root.x, root.y)
}

test2.qml

import QtQuick 2.5
import QtQuick.Controls 1.4

ApplicationWindow {
    visible: true
    width: 200
    height: 240
    x: manager.position.x
    y: manager.position.x
    Text {
        text: qsTr("main2")
    }
}