如何将父级发送到新的 ApplicationWindow

How can I send parent to a new ApplicationWindow

我想恢复master的位置和大小"main.qml"。但是我不知道如何声明新window的父级。 如果我直接从 javascript 中的 window main.qml 打开 window 没有问题,但是通过 python 我看不出如何。

我想我必须使用 "self.win" 但如何声明它?

感谢您的回复。

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")}
}

我想我找到了:

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)
...

并且在文件 qml

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

我可以恢复这样的价值。这个对吗?有没有更常规的方式?

虽然解决方案在这种情况下有效,但在更实际的情况下可能会失败,因为 QML 加载是异步的,但您的过程是同步的,因此每个 QML 可以加载许多组件。

解决方案是创建一个 QObject 并使用 setContextProperty() 将其导出到 QML,以便它可以从通过 QQmlApplicationEngine 加载的所有 QML 访问。该 QObject 必须有一个 属性,它是您要获取的 属性 的镜像。

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")
    }
}