【问题标题】:Connect QML signal to PySide2 slot将 QML 信号连接到 PySide2 插槽
【发布时间】:2019-08-23 02:43:12
【问题描述】:

我有一些使用 Qt/C++ 的经验,现在我想切换到 PySide2 + QML。我想将 ui 信号(例如单击按钮)连接到 python 插槽

我见过很多例子,但它们都不同,我猜 PyQt/PySide 现在变化很快

您能否提供将 QML 信号连接到 PySide Slot 的现代且简洁的方法?例如单击按钮以在 python 控制台中打印一些文本。这是我的简单代码示例

ma​​in.py

from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine

def test_slot(string): # pseudo slot
    print(string)

if __name__ == "__main__":
    app = QGuiApplication()
    engine = QQmlApplicationEngine('main.qml')
    exit(app.exec_())

ma​​in.qml

import QtQuick 2.13
import QtQuick.Controls 2.13

ApplicationWindow {
    visible: true

    Button {
        anchors.centerIn: parent
        text: "Example"
        onClicked: test_slot("Test") //pseudo signal
    }
}

【问题讨论】:

    标签: python qml pyside2


    【解决方案1】:

    在这些情况下的最佳实践是创建一个 QObject,将其导出到 QML 并在那里建立连接,就像在 C++ 中一样。

    ma​​in.py

    from PySide2.QtCore import QObject, QUrl, Slot
    from PySide2.QtGui import QGuiApplication
    from PySide2.QtQml import QQmlApplicationEngine
    
    
    class Foo(QObject):
        @Slot(str)
        def test_slot(self, string):
            print(string)
    
    
    if __name__ == "__main__":
        import os
        import sys
    
        app = QGuiApplication()
        foo = Foo()
        engine = QQmlApplicationEngine()
        engine.rootContext().setContextProperty("foo", foo)
        qml_file = "main.qml"
        current_dir = os.path.dirname(os.path.realpath(__file__))
        filename = os.path.join(current_dir, qml_file)
        engine.load(QUrl.fromLocalFile(filename))
        if not engine.rootObjects():
            sys.exit(-1)
        sys.exit(app.exec_())
    

    ma​​in.qml

    import QtQuick 2.13
    import QtQuick.Controls 2.13
    
    ApplicationWindow {
        visible: true
    
        Button {
            anchors.centerIn: parent
            text: "Example"
            onClicked: foo.test_slot("Test")
        }
    }
    

    注意:所有 C++/QML 良好实践也适用于 Python/QML,只需极少的更改和限制。

    【讨论】:

      【解决方案2】:

      eyllanesc 的解决方案是直接同步调用方法test_slot。当test_slot 小而快时很好。但是如果包含很多操作,QML GUI 每次都会挂起,直到返回test_slot

      最类似于 Qt 的方式是 slog-signal 元对象连接(参见下面的 #CHANGES//CHANGES):

      main.py

      from PySide2.QtCore import QObject, QUrl, Slot, Signal, Qt
      from PySide2.QtGui import QGuiApplication
      from PySide2.QtQml import QQmlApplicationEngine
      
      class Foo(QObject):
          @Slot(str)
          def test_slot(self, input_string : str):
              print(input_string)
      
      if __name__ == "__main__":
          import os
          import sys
      
          app = QGuiApplication()
          foo = Foo()
          engine = QQmlApplicationEngine()
          
          #CHANGES: line excluded engine.rootContext().setContextProperty("foo", foo)
          
          qml_file = "main.qml"
          current_dir = os.path.dirname(os.path.realpath(__file__))
          filename = os.path.join(current_dir, qml_file)
          engine.load(QUrl.fromLocalFile(filename))
          if not engine.rootObjects():
              sys.exit(-1)
          
          #CHANGES: connect QML signal to Python slot
          engine.rootObjects()[0].test_signal.connect(foo.test_slot, type=Qt.ConnectionType.QueuedConnection)
          
          sys.exit(app.exec_())
      

      main.qml

      import QtQuick 2.13
      import QtQuick.Controls 2.13
      
      ApplicationWindow {
          visible: true
          
          //CHANGES: declare signal
          signal test_signal(string input_string)
      
          Button {
              anchors.centerIn: parent
              text: "Example"
      
              //CHANGES: emit signal
              onClicked: test_signal("Test string")
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多