Как получить доступ к элементам управления QML \ QtQuick из PySide? - PullRequest
1 голос
/ 06 марта 2019

Я пытаюсь получить доступ к элементу управления FileDialog из файла python, который запускает механизм QQmlApplication для получения свойства пути к файлу. Я установил сигнал в файле .qml, однако я не могу получить доступ к диалоговому окну файла по идентификатору в файле python для настройки слота. Метод findChild в application.py возвращает None. Вот код:

application.py

import sys
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine, QQmlFileSelector

sys_argv = sys.argv
sys_argv += ['--style', 'material']
app = QGuiApplication(sys_argv)

window = QQmlApplicationEngine()
window.load("QML/main.qml")

fileDialog = window.findChild(QQmlFileSelector, "fileDialog")
print(fileDialog)

app.exec_()

Page1.qml

import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Dialogs 1.2

Page {
    width: 600
    height: 400

    header: Label {
        text: qsTr("Prepare Data")
        horizontalAlignment: Text.AlignHCenter
        font.pixelSize: Qt.application.font.pixelSize * 2
        padding: 10
    }

    Button {
        text: qsTr("Load data")
        anchors.centerIn: parent
        onClicked: fileDialog.visible = true
        padding: 10
    }

    signal folderSelected()

    FileDialog {
        id: fileDialog
        selectFolder: true
        title: qsTr("Select the data directory")
        folder: shortcuts.home
        onAccepted: {
            parent.folderSelected()
        }
    }
}

main.qml

import QtQuick 2.0
import QtQuick.Controls 2.12
import QtQuick.Controls.Material 2.12

ApplicationWindow{
    visible: true
    title: qsTr("Main window")
    width: 1000
    height: 800

    Material.theme: Material.Light
    Material.accent: Material.Orange

    SwipeView {
        id: swipeView
        anchors.fill: parent

        Page1 {
        }

        Page2 {
        }

        Page3 {
        }

    }
}

1 Ответ

1 голос
/ 06 марта 2019

В старом ответе объясните в разделе Pushing References на QML , как обновить некоторый объект python из QML, эта методология рекомендована Qt, и именно онаследует использовать сейчас.С вашим текущим методом вам нужно установить имя объекта, которое может быть проблематичным во многих случаях.

Таким образом, решение состоит в том, чтобы создать объект QOb, который мы экспортируем в QML, и обновить свойство qproperty, это выдаст сигнал, который мы подключаемв слот, где мы можем сделать логику, которую мы хотим.С другой стороны, FileDialog возвращает URL, поэтому свойство должно быть QUrl:

main.qml

import os
import sys
from PySide2 import QtCore, QtGui, QtQml

class FileManager(QtCore.QObject):
    file_url_Changed = QtCore.Signal(QtCore.QUrl)

    def __init__(self, parent=None):
        super(FileManager, self).__init__(parent)
        self._file_url = QtCore.QUrl()

    def get_file_url(self):
        return self._file_url

    def set_file_url(self, file_url):
        if self._file_url != file_url:
            self._file_url = file_url
            self.file_url_Changed.emit(self._file_url)

    file_url = QtCore.Property(QtCore.QUrl, fget=get_file_url, fset=set_file_url, notify=file_url_Changed)

@QtCore.Slot(QtCore.QUrl)
def on_file_url_changed(file_url):
    print(file_url.toLocalFile())

if __name__ == '__main__':
    sys.argv += ['--style', 'material']
    app = QtGui.QGuiApplication(sys.argv)

    file_manager = FileManager()
    file_manager.file_url_Changed.connect(on_file_url_changed)

    engine = QtQml.QQmlApplicationEngine()
    engine.rootContext().setContextProperty("file_manager", file_manager)
    file = os.path.join(os.path.dirname(os.path.realpath(__file__)), "QML", "main.qml")
    engine.load(QtCore.QUrl.fromLocalFile(file))
    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(app.exec_())

Page1.qml

import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Dialogs 1.2

Page {
    width: 600
    height: 400

    header: Label {
        text: qsTr("Prepare Data")
        horizontalAlignment: Text.AlignHCenter
        font.pixelSize: Qt.application.font.pixelSize * 2
        padding: 10
    }

    Button {
        text: qsTr("Load data")
        anchors.centerIn: parent
        onClicked: fileDialog.visible = true
        padding: 10
    }

    FileDialog {
        id: fileDialog
        selectFolder: true
        title: qsTr("Select the data directory")
        folder: shortcuts.home
        onAccepted: {
            file_manager.file_url = fileDialog.fileUrl // <---
        }
    }
}
...