1

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?

Attila49
  • 59
  • 5
  • I do not understand you, explain yourself better. What is your underlying problem? – eyllanesc Oct 13 '19 at 15:47
  • I want to positionne the second window like the first and I need the parameters of the first (x,y). – Attila49 Oct 13 '19 at 16:03
  • I understood, but I still have a doubt, do you want both windows to **always** have the same position or **only at the beginning**? – eyllanesc Oct 13 '19 at 16:07
  • Just on start. For put the second in the center of the first. Is what I found is correct ? (I have test many thing and that work so perhaps have better script for have the position of the master screen) – Attila49 Oct 13 '19 at 16:12
  • It's possible to send parent to the second window ? When I test, I have 2 window open in toolbar but it's the same soft. So How can I open the second window and no have a second window in toolbar ? – Attila49 Oct 13 '19 at 16:31
  • Qt will open 2 elements in the toolbar because there are 2 windows without parents, that is the normal behavior so you can not what you require. – eyllanesc Oct 13 '19 at 16:41

1 Answers1

2

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")
    }
}
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thank you for the answer. I have test but there is a small problem: "test2.qml: 8: ReferenceError: manager is not defined". Why is it recognized in the first file but not in the second? – Attila49 Oct 13 '19 at 16:54
  • @Attila49 Are you using only my code or have you modified it? I have tested my code with PyQt5 5.13.1 and it works correctly. – eyllanesc Oct 13 '19 at 16:56
  • As much for me ... yet I had done a copy-pasted. I redid a copied pasted and actually it works perfectly. Well it remains for me to study all that to understand well. Thank you very much for your help. – Attila49 Oct 13 '19 at 17:18