2013-10-02 91 views
8

如何將python方法/插槽連接到QML信號?它看起來像QtObject.connect()用於在PyQt4中工作,但它是no longer available in PyQt5PyQt5 QML信號到Python插槽?

#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事件槽在該對象上但方法似乎迂迴。有沒有更好的辦法?

回答

13

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) 
... 
+0

的偉大工程,找到更多的信息!謝謝! – berg

1

我會推薦子分類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