Как отправить родителя в новое окно ApplicationWindow? - PullRequest
1 голос
/ 13 октября 2019

Я хочу восстановить позицию и размер мастера "main.qml". Но я не знаю, как объявить родителем нового окна. У меня нет проблем, если я открываю окно прямо из окна main.qml в javascript, но через 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")}
}

я могу восстановить значение таким образом. Это верно? Есть ли более обычный способ?

1 Ответ

2 голосов
/ 13 октября 2019

Хотя решение работает в этом случае, оно может дать сбой в более реальных случаях, когда каждый QML может загружать много компонентов, поскольку загрузка QML асинхронна, но ваша процедура синхронна.

Решение состоит в создании QObject иэкспортируйте его в QML с помощью setContextProperty (), чтобы он был доступен из всех QML, которые загружаются через QQmlApplicationEngine. Этот 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")
    }
}
...