2013-10-02 18 views
8

W jaki sposób można podłączyć metodę Pythona do sygnału QML? Wygląda na to, że QtObject.connect() był używany w PyQt4, ale jest to no longer available in PyQt5.PyQt5 QML Signal to Python Slot?

#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_()) 

Niektóre przykłady pyqt przechodzi obiekt w kontekście QML poprzez „setContextProperty”, a następnie przekazywanie zdarzeń QML szczelinom w tym przedmiocie, ale takie podejście wydaje ronda. Czy istnieje lepszy sposób?

Odpowiedz

13

qml_rectangle.mousePressEvent nie jest sygnałem, jest to funkcja obsługi zdarzeń wywoływana w zdarzeniach myszy, więc nie można się z nią połączyć. Możesz po prostu zastąpić go funkcją obsługi (qml_rectangle.mousePressEvent = on_qml_mouse_clicked), ale to nie jest bardzo czysty sposób pracy z Qt.

Lepszym sposobem byłoby określenie sygnału w pliku QML i emitują go z prostokąta onClicked Handler:

import QtQuick 2.0 

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

Następnie można po prostu połączyć się z nim z kodu Pythona:

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

qml_rectangle.clicked.connect(on_qml_mouse_clicked) 
... 
+0

działa świetnie! Dziękuję Ci! – berg

1

Polecam podklasę QQuickView i ustawienie właściwości w jego kontekście głównym , na przykład MainWindow. Teraz wszystko, co musisz zrobić, to dodanie funkcji w tej klasie z dekoracjami takimi jak @pyqtSlot („”) QString, a następnie można ustawić obsługi zdarzeń z onClicked: MainWindow.FunctionName (Arguments_According_To_Decoration)

Następnie Twój main.py wyglądałby następująco

#!/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_()) 

I sample.qml jak tak

import QtQuick   2.0 
import QtQuick.Controls 2.2 

Rectangle { 
    width: 200; height: 200 

    Button { 
     text: "print Hello World" 
     onClicked: MainWindow.Print('hello world') 
    } 
} 

można znaleźć więcej informacji w docs

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