несколько вопросов о QML и PySide2 - PullRequest
1 голос
/ 25 февраля 2020

У меня есть следующие случаи, я хочу использовать несколько Qml: "welcome.qml", "create.qml", "dashboard.qml"

, в каких случаях использовать QQuickview или QqmlApplicationEngine.?

Я использую «QQmlAplicatiobEngine» и ищу в объекте findChild, чтобы получить сигнал, и обрабатываю лог c. Если сигнал завершает условие, я использую engine.load для загрузки другого QML.

python:

class guiBackend(QObject):

    def __init__(self):
        self.engine = QQmlApplicationEngine()
        self.context = self.engine.rootContext()
        self.context.setContextProperty("main", self.engine)
        self.welcome()

    def welcome(self):
        self.engine.load("welcome.qml")
        self.engine.rootObjects()[0].show()
        ob = self.engine.rootObjects()[0]
        next = ob.findChild(QObject, "timer")
        print(dir(next))
        if  path.exists('data.some'):
            next.change.connect(self.open_account)
        else:
            next.change.connect(self.create_account)
    def create(self):
        self.engine.rootObjects()[0].close()
        self.engine.load("create.qml")
        self.engine.rootObjects()[1].show()
        add = ob.findChild(QObject, "addWallet")
        recovery = ob.findChild(QObject, "recovery")
        add.change.connect(self.add_account)
        recovery.change.connect(self.recovery)
        #self.open_account load dashboard.qml and self.account load form.qml

if __name__ == "__main__":
    app = QGuiApplication(sys.argv)
    gui = guiBackend()
    sys.exit(app.exec_())

Qml:

ApplicationWindow {
    id: welcome
    width: 650; height: 390
    opacity: 1
    visible: true
    minimumHeight: 232
    minimumWidth:226
    title: "open account"
    flags: Qt.SplashScreen
    Item {

        id: element
        x: 9
        y: 88
        width: 560
        height: 300
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter
        Timer {
        signal change
        objectName: "timer"
        interval: 5000; running: true; repeat: false
        onTriggered: change()
        }
        Image {
            id: image
            x: 130
            y: 60
            width: 342
            height: 188
            anchors.verticalCenterOffset: -56
            anchors.horizontalCenterOffset: 0
            anchors.verticalCenter: parent.verticalCenter
            anchors.horizontalCenter: parent.horizontalCenter
            source: "neirons_logo.png"
            fillMode: Image.PreserveAspectFit
        }

        AnimatedImage {
            id: animatedImage
            x: 236
            y: 200
            width: 100
            height: 100
            source: "loading.gif"
        }
    }
}

create.qml:

ApplicationWindow {
    id: create
    width: 210; height: 210

    Rectangle {
        id: rectangle
        x: 70
        y: 132
        width: 200
        height: 200
        color: "#72ded8"
        anchors.verticalCenterOffset: 0
        anchors.horizontalCenterOffset: 0
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter

        ColumnLayout {
            x: 60
            y: 73
            width: 109
            height: 128
            anchors.verticalCenter: parent.verticalCenter
            anchors.horizontalCenter: parent.horizontalCenter

            TextInput {
                id: nameAccount
                objectName: textAccount
                text: qsTr("nameAccount")
                Layout.fillWidth: true
                Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
                Layout.preferredHeight: 20
                Layout.preferredWidth: 80
                verticalAlignment: Text.AlignVCenter
                font.pixelSize: 12
            }

            TextInput {
                id: nameAccount
                objectName: textAccount
                text: qsTr("Name Account")
                Layout.fillWidth: true
                Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
                Layout.preferredHeight: 20
                Layout.preferredWidth: 80
                font.pixelSize: 12
            }
        }

        Button {
            signal addinfo
            id: submitNameAccount
            objectName: submit
            x: 50
            y: 134
            width: 81
            height: 23
            text: qsTr("Add")
            font.bold: true
            font.pointSize: 12
            anchors.horizontalCenter: parent.horizontalCenter
            onClicked: addinfo()
    }


}

Лучше с QQuickview или QQmlAplicationEngine.

1 Ответ

0 голосов
/ 25 февраля 2020

Из того, что дает ОП, я укажу следующие аспекты:

  • Когда следует использовать QQmlAplicationEngine или QQuickview? лучше QQmlAplicationEngine или QQuickview?

    Использование одного или другого зависит от элемента root в QML, если root - это Window или ApplicationWindow, то вы должны использовать QQmlAplicationEngine, если вместо этого это Item или его производные, вы можете использовать QQuickView. Так что для вышесказанного одно не лучше другого. Что произойдет, если я загружу QML с root Window или ApplicationWindow с QQuickView? Тогда он покажет 2 windows: один будет из QQuickView, а другой из Window или ApplicationWindow. Что если я загружу QML с Item с помощью QQmlApplicationEngine? Что ж, вам нужно будет поместить его в окно, как указано в документах :

    В отличие от QQuickView, QQmlApplicationEngine не создает автоматически окно root. Если вы используете визуальные элементы из Qt Quick, вам нужно будет поместить их в окно.

  • Не обращаться к элементам QML из python / C ++

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


Мы применим вышеуказанные концепции к коду, предоставленному OP (там типы, которые я исправил).

  • Прежде всего, поскольку корни - ApplicationWindow, следует использовать QQmlApplicationEngine.

  • Вместо создавая сигнал «изменение» в каждом элементе, вы можете экспортировать бэкэнд в QML, используя setContextProperty, а затем напрямую вызывать слоты. Получить объект с помощью rootObjects () опасно, поскольку существуют qmls, которые загружаются асинхронно, вместо этого используйте сигнал objectCreated.

main.py

import os

from PyQt5 import QtCore, QtGui, QtQml

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


class Backend(QtCore.QObject):
    def __init__(self, parent=None):
        super().__init__(parent)

        self._engine = QtQml.QQmlApplicationEngine()
        self._welcome = None
        self._wallet = None
        self.engine.objectCreated.connect(self.on_object_created)
        self.engine.rootContext().setContextProperty("backend", self)

        self.load_welcome()

    @property
    def engine(self):
        return self._engine

    @property
    def welcome(self):
        return self._welcome

    @property
    def wallet(self):
        return self._wallet

    @staticmethod
    def create_url(qml):
        return QtCore.QUrl.fromLocalFile(os.path.join(CURRENT_DIR, qml))

    def load_welcome(self):
        self.engine.load(self.create_url("welcome.qml"))

    @QtCore.pyqtSlot(QtCore.QObject, QtCore.QUrl)
    def on_object_created(self, obj, url):
        if url == self.create_url("welcome.qml"):
            self._welcome = obj
        elif url == self.create_url("wallet.qml"):
            self._wallet = obj

    @QtCore.pyqtSlot()
    def create_wallet(self):
        self.welcome.close()
        self.engine.load(self.create_url("wallet.qml"))

    @QtCore.pyqtSlot()
    def add_info(self):
        print("add_info")


if __name__ == "__main__":
    import sys

    app = QtGui.QGuiApplication(sys.argv)
    backend = Backend()

    sys.exit(app.exec_())

welcome.qml

import QtQuick 2.14
import QtQuick.Controls 2.14

ApplicationWindow {
    id: root
    width: 650; height: 390
    opacity: 1
    visible: true
    minimumHeight: 232
    minimumWidth:226
    title: "open account"
    flags: Qt.SplashScreen
    Item {
        id: element
        x: 9
        y: 88
        width: 560
        height: 300
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter
        Timer {
            interval: 5000; running: true; repeat: false
            onTriggered: backend.create_wallet()
        }
        Image {
            id: image
            x: 130
            y: 60
            width: 342
            height: 188
            anchors.verticalCenterOffset: -56
            anchors.horizontalCenterOffset: 0
            anchors.verticalCenter: parent.verticalCenter
            anchors.horizontalCenter: parent.horizontalCenter
            source: "neirons_logo.png"
            fillMode: Image.PreserveAspectFit
        }

        AnimatedImage {
            id: animatedImage
            x: 236
            y: 200
            width: 100
            height: 100
            source: "loading.gif"
        }
    }
}

wallet.qml

import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14


ApplicationWindow {
    id: root
    visible: true
    width: 210; height: 210

    Rectangle {
        id: rectangle
        x: 70
        y: 132
        width: 200
        height: 200
        color: "#72ded8"
        anchors.verticalCenterOffset: 0
        anchors.horizontalCenterOffset: 0
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter

        ColumnLayout {
            x: 60
            y: 73
            width: 109
            height: 128
            anchors.verticalCenter: parent.verticalCenter
            anchors.horizontalCenter: parent.horizontalCenter

            TextInput {
                id: nameAccount1
                text: qsTr("nameAccount")
                Layout.fillWidth: true
                Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
                Layout.preferredHeight: 20
                Layout.preferredWidth: 80
                verticalAlignment: Text.AlignVCenter
                font.pixelSize: 12
            }

            TextInput {
                id: nameAccount2
                text: qsTr("Name Account")
                Layout.fillWidth: true
                Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
                Layout.preferredHeight: 20
                Layout.preferredWidth: 80
                font.pixelSize: 12
            }
        }

        Button {
            id: submitNameAccount
            x: 50
            y: 134
            width: 81
            height: 23
            text: qsTr("Add")
            font.bold: true
            font.pointSize: 12
            anchors.horizontalCenter: parent.horizontalCenter
            onClicked: backend.add_info()
        }
    }
}
...