python方法/插槽连接到QML信号?看起来QtObject.connect()曾经在PyQt4中工作,但在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 事件中继到该对象上的插槽,但这种方法似乎是迂回的。有没有更好的方法?
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)
...
我建议对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_())
和样本.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