【问题标题】:PyQt5 QML Signal to Python Slot?PyQt5 QML 信号到 Python 插槽?
【发布时间】:2013-10-08 11:48:56
【问题描述】:

如何将 python 方法/槽连接到 QML 信号?看起来 QtObject.connect() 曾经在 PyQt4 中工作,但它是 no longer available in PyQt5

#Sample QML File (stack.qml)

import QtQuick 2.0

Rectangle {
    MouseArea {
        anchors.fill: parent
        onClicked: {
           // relay this to python
        }
    }
}

--

#Sample Python File
from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQuick import QQuickView

if __name__ == '__main__':
    import os
    import sys

    app = QGuiApplication(sys.argv)

    view = QQuickView()
    view.setWidth(500)
    view.setHeight(500)
    view.setTitle('Hello PyQt')
    view.setResizeMode(QQuickView.SizeRootObjectToView)
    view.setSource(QUrl.fromLocalFile(os.path.join(os.path.dirname(__file__),'stack.qml')))

    def on_qml_mouse_clicked(mouse_event):
        print 'mouse clicked'

    view.show()
    qml_rectangle = view.rootObject()

    # this technique doesn't work #############################
    qml_rectangle.mousePressEvent.connect(on_qml_mouse_clicked)

    sys.exit(app.exec_())

一些 PyQT 示例通过“setContextProperty”将对象传递到 QML 上下文,然后将 QML 事件中继到该对象上的插槽,但这种方法似乎是迂回的。有没有更好的办法?

【问题讨论】:

    标签: qt pyqt qml pyqt5


    【解决方案1】:

    qml_rectangle.mousePressEvent 不是信号,它是在鼠标事件上调用的事件处理程序,因此您无法连接到它。您可以将其替换为您的处理程序函数 (qml_rectangle.mousePressEvent = on_qml_mouse_clicked),但这不是使用 Qt 的一种非常干净的方式。

    更好的方法是在你的 qml 文件中定义一个信号并从矩形的 onClicked 处理程序中发出它:

    import QtQuick 2.0
    
    Rectangle {
        signal clicked()
        MouseArea {
            anchors.fill: parent
            onClicked: {
               parent.clicked()  // emit the parent's signal
            }
        }
    }
    

    然后你可以从你的 python 代码连接到它:

    ...
    def on_qml_mouse_clicked():
        print('mouse clicked')
    
    qml_rectangle.clicked.connect(on_qml_mouse_clicked)
    ...
    

    【讨论】:

      【解决方案2】:

      我建议对QQuickView 进行子类化并在其根上下文 上设置一个属性,例如MainWindow。现在您需要做的就是在该类中添加带有 @pyqtSlot('QString') 等装饰的函数,然后您可以使用 onClicked 设置事件处理程序: MainWindow.FunctionName(Arguments_According_To_Decoration )

      那么你的 main.py 应该是这样的

      #!/bin/env python3
      # -*- coding: utf-8 -*-
      from PyQt5.QtCore    import pyqtSlot
      from PyQt5.QtCore    import QUrl
      from PyQt5.QtQuick   import QQuickView
      from PyQt5.QtWidgets import QApplication
      import sys
      
      class MainWindow(QQuickView):
          def __init__(self):
              super().__init__()
              self.setSource(QUrl('sample.qml'))
              self.rootContext().setContextProperty("MainWindow", self)
              self.show()
      
          @pyqtSlot('QString')
          def Print(self, value):
              print(value)
      
      if __name__ == '__main__':
          app = QApplication(sys.argv)
          w = MainWindow()
          sys.exit(app.exec_())
      

      sample.qml 像这样

      import QtQuick          2.0
      import QtQuick.Controls 2.2
      
      Rectangle {
          width: 200; height: 200
      
          Button {
            text: "print Hello World"
            onClicked: MainWindow.Print('hello world')
          }
      }
      

      您可以在文档中找到更多信息

      http://pyqt.sourceforge.net/Docs/PyQt5/signals_slots.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-08
        • 1970-01-01
        • 1970-01-01
        • 2019-04-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多