Как модулировать создание свойств в PySide - PullRequest
0 голосов
/ 20 апреля 2020

Я в основном следую инструкциям здесь для использования свойств, и я мог бы просто использовать данный объект Person в качестве внутреннего, но это не очень полезно. Я пытаюсь понять, как сделать следующие две вещи:

  1. Использовать несколько экземпляров нескольких таких классов в бэкэнде и соединить их так, чтобы PySide / QML не жаловался
  2. Разрешить настройку серверной части модулями во время выполнения (т. Е. Я в конечном итоге хочу компонентизировать приложение - иметь разные компоненты, реализующие интерфейс, компонент вносит свой вклад как в GUI, так и в серверную часть; но этот вопрос касается только бэкэнд)

Это в отличие от простого определения всех этих свойств вместе с их установщиком и геттером в основном бэкэнд-классе (что я смог сделать), что я имею в виду под modularize в вопросе.

Я изменяю пример Person по ссылке, чтобы сделать его чем-то, что пользовательский интерфейс может изменить, и присвоил ему дополнительный атрибут для ударов ...

person.py

from PySide2.QtCore import QObject, Signal, Property

class Person(QObject):

    def __init__(self, name, age):
        QObject.__init__(self)
        self._name = name
        self._age = age

    def getName(self):
        return self._name

    def setName(self, name):
        print(f"Setting name to {name}")
        self._name = name

    def getAge(self):
        return self._age

    def setAge(self, age):
        print(f"Setting age to {age}")
        self._age = age

    @Signal
    def name_changed(self):
        pass

    @Signal
    def age_changed(self):
        pass

    name = Property(str, getName, setName, notify=name_changed)
    age = Property(str, getAge, setAge, notify=age_changed)

В качестве примера я создам два экземпляра Person. Первый экземпляр, который я создал как член класса. Это не совсем то, что я хочу, но ближе напоминает способ, которым свойства использовались в ссылке. Второй экземпляр - это то, что я действительно хочу, это то, что свойства являются членами экземпляра, так что я могу добавить их из другого места приложения во время выполнения. Ни один из методов в настоящее время не работает

main.py

import sys
from os.path import abspath, dirname, join

from PySide2.QtCore import QObject, Property, Signal
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine

from person import Person

class Backend(QObject):

    def __init__(self):
        QObject.__init__(self)

    def registerProperty(self, name : str, prop):
        setattr(self, name, prop)

    person1 = Person("Jill", 29)

if __name__ == '__main__':

    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()
    context = engine.rootContext()

    # Instance of the Python object
    backend = Backend()

    # simulate properties added by another module
    backend.registerProperty("person2", Person("Jack", 30))

    qmlFile = join(dirname(__file__), 'view3.qml')
    engine.load(abspath(qmlFile))

    # Expose the Python object to QML
    context.setContextProperty("backend", backend)

    # I tried this but it did nothing
    # context.setContextProperty("backend.jack", backend.jack)
    # context.setContextProperty("backend.jill", backend.jill)

    if not engine.rootObjects():
        sys.exit(-1)

    sys.exit(app.exec_())

наконец, файл view3.qml просто

import QtQuick 2.0
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12
import QtQuick.Window 2.12

ApplicationWindow {

    visible: true

    ColumnLayout {
        TextField {
            implicitWidth: 200
            onAccepted: {
                backend.person1.name = text
            }
        }
        TextField {
            implicitWidth: 200
            onAccepted: {
                backend.person1.age = text
            }
        }
        TextField {
            implicitWidth: 200
            onAccepted: {
                backend.person2.name = text
            }
        }
        TextField {
            implicitWidth: 200
            onAccepted: {
                backend.person2.age = text
            }
        }
    }
}

Когда я пытаюсь установить любое из значений в пользовательском интерфейсе, ошибка всегда одинакова (ошибка появляется в файле QML)

TypeError: Value is undefined and could not be converted to an object

В конечном счете, я хотел бы, чтобы такие объекты были вложены на любую произвольную глубину , Есть ли способ достичь того, что я пытаюсь сделать здесь? Или я, возможно, совершенно не в курсе того, как я об этом говорю?

...