Сигнал PySide2 (5.14.2) с именованным параметром - PullRequest
1 голос
/ 03 апреля 2020

Аргумент PySide Signal не может быть получен из QML

Согласно этому сообщению, PySide2 (версия> 5.12.5) поддерживает сигнал с именованным параметром, как в PyQt5. Поэтому я попытался здесь, в PySide2 (5.14.2), и получил ошибку типа

file: /// E: /QML/projects/main.qml: 72: 5: Невозможно назначить несуществующему свойство "onSpitInput"

Скажите, что здесь не так.

* app.py

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

class controller(QtCore.QObject):
    spitInput = QtCore.Signal(str, arguments=['userinput'])

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

    @QtCore.Slot(int, result=list)
    def getUserInput(self, first):
        self.spitInput.emit(str(first) + 'is the value given by user')


controller = controller()
app = QtWidgets.QApplication(sys.argv)
current_dir = os.path.dirname(os.path.realpath(__file__))
engine = QtQml.QQmlApplicationEngine()
engine.addImportPath(current_dir)
engine.rootContext().setContextProperty("controller", controller)
filename = os.path.join(current_dir, "main.qml")
engine.load(QtCore.QUrl.fromLocalFile(filename))

if not engine.rootObjects():
    sys.exit(-1)
engine.quit.connect(app.quit)
sys.exit(app.exec_())

main.qml

 import QtQuick 2.13
 import QtQuick.Controls 2.13

 ApplicationWindow {
  id: root
  visible: true
  width: 640
  height: 480
  title: qsTr("Hello World")

  Rectangle {
      id: bufferRectId
      width: 640
      height: 480
      anchors.fill: parent

      TextField{
          id:firstTextInputFieldId
          font.pointSize: 16
          anchors.top: parent.top
          anchors.left: parent.left
          anchors.topMargin: 10
          anchors.horizontalCenter: parent.horizontalCenter
      }

      Button{
          id:calcButtonId
          width: 60
          height: 30
          text: "Click Me"
          anchors.horizontalCenter: parent.horizontalCenter
          anchors.top: parent.top
          anchors.topMargin: 60

          onClicked: {
              controller.getUserInput(firstTextInputFieldId.text)
          }
      }
  }

  onSpitInput: console.log(userinput)
 }

1 Ответ

2 голосов
/ 03 апреля 2020

Когда вы используете следующий код:

ApplicationWindow {
   id: root
   // ...
   onSpitInput: console.log(userinput)
}

Вы заявляете, что onSpitInput принадлежит «root», что явно ложно, поскольку оно принадлежит «контроллеру» и, следовательно, дает сбой.

В этом случае вы должны использовать Connections:

import QtQuick 2.13
import QtQuick.Controls 2.13

ApplicationWindow {
    id: root
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
    Rectangle {
        id: bufferRectId
        anchors.fill: parent
        TextField{
            id:firstTextInputFieldId
            font.pointSize: 16
            anchors.top: parent.top
            anchors.left: parent.left
            anchors.topMargin: 10
            anchors.horizontalCenter: parent.horizontalCenter
        }
        Button{
            id:calcButtonId
            width: 60
            height: 30
            text: "Click Me"
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.top: parent.top
            anchors.topMargin: 60
            onClicked: controller.getUserInput(firstTextInputFieldId.text)
        }
    }
    <b>Connections{
        target: controller
        onSpitInput: console.log(userinput)
    }</b>
}

С другой стороны, существует другая ошибка: метод getUserInput получает строку и ничего не возвращает, но в соответствии с к вашему коду он должен получить целое число и вернуть список. Правильно:

import os
import sys

from PySide2 import QtCore, QtGui, QtWidgets, QtQml


class controller(QtCore.QObject):
    spitInput = QtCore.Signal(str, arguments=["userinput"])

    <b>@QtCore.Slot(str)
    def getUserInput(self, first):
        self.spitInput.emit("{} is the value given by user".format(first))</b>


if __name__ == "__main__":

    controller = controller()
    app = QtWidgets.QApplication(sys.argv)
    current_dir = os.path.dirname(os.path.realpath(__file__))
    engine = QtQml.QQmlApplicationEngine()
    engine.addImportPath(current_dir)
    engine.rootContext().setContextProperty("controller", controller)
    filename = os.path.join(current_dir, "main.qml")
    engine.load(QtCore.QUrl.fromLocalFile(filename))

    if not engine.rootObjects():
        sys.exit(-1)
    engine.quit.connect(app.quit)
    sys.exit(app.exec_())
...