QMLとPython通信


Python 3とQML通信については、実際にはPyQt 5+QML+Python 3のハイブリッドプログラミングが必要です.QMLはグラフィックインタフェースを作るのが簡単ですが、機能実装はPythonのほうがいいです.QMLもJavaScriptコードを埋め込んで実現できますが、Pythonで実現するよりは、コードが簡潔で分かりやすいです.
次の例では、次の接続を参照します.
Connecting QML signals in PySide:
http://qt-project.org/wiki/Connecting_QML_Signals_in_PySide 
PyQt 5.1.1 Reference Guide -> Support for Signals and Slots:
http://pyqt.sourceforge.net/Docs/PyQt5/signals_slots.html?highlight=pyqtslot#PyQt5.QtCore.pyqtSlot
(1)QML明示的な呼び出しPython関数
クラスを定義し、QtCoreを継承します.QObjectオブジェクト、および@修飾子を使用してpyqtSlotを修飾
class MyClass(QObject):
    @pyqtSlot(str)    #          
    def outputString(self, string):
        """
          :      
          :      string
           :  
        """
        print(string)

rootContextオブジェクトを作成し、setContextProperty(string,object)を使用してオブジェクトを登録することで、QMLでこの関数を呼び出すことができます.
context = view.rootContext()
context.setContextProperty("con", con)

以下に完全な例を示します.
この例を実行すると、マウスをクリックすると、コンソールに文字列が印刷されます.
Python 3コード:
# -*- coding: GBK -*-
from PyQt5.QtCore import QUrl, QObject, pyqtSlot
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQuick import QQuickView

class MyClass(QObject):
    @pyqtSlot(str)    #      str  
    def outputString(self, string):
        """
          :      
          :      string
           :  
        """
        print(string)
        
if __name__ == '__main__':
    path = 'test.qml'   #    QML  
    app = QGuiApplication([])
    view = QQuickView()
    con = MyClass()
    context = view.rootContext()
    context.setContextProperty("con", con)
    view.engine().quit.connect(app.quit)
    view.setSource(QUrl(path))
    view.show()
    app.exec_()

QMLコード(ファイル名はtest.qmlとして保存):
import QtQuick 2.0
Rectangle {
    width: 320; height: 240
    color: "lightgray"
    Text {
        id: txt
        text: "Clicked me"
        font.pixelSize: 20
        anchors.centerIn: parent
    }
    MouseArea {
        id: mouse_area
        anchors.fill: parent  //     
        onClicked: {
           con.outputString("Hello, Python3")
        }
    }
}

実行結果は次のとおりです.
QML与Python通信
(2)QMLはPython関数を呼び出し,返す.
この例は同じですが、今回Pythonを呼び出す関数には戻り値機能があります.
以下に完全な例を示します.
プログラムを実行したら、マウスをクリックすると左上に数字30が表示されます.
Python 3コード:
# -*- coding: GBK -*-
from PyQt5.QtCore import QUrl, QObject, pyqtSlot
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQuick import QQuickView
class MyClass(QObject):
    @pyqtSlot(int, result=str)    #     ,     int  ,    str  
    def returnValue(self, value):
        """
          :      
          :   value
           :    
        """
        return str(value+10)
if __name__ == '__main__':
    path = 'test.qml'   #    QML  
    app = QGuiApplication([])
    view = QQuickView()
    con = MyClass()
    context = view.rootContext()
    context.setContextProperty("con", con)
    view.engine().quit.connect(app.quit)
    view.setSource(QUrl(path))
    view.show()
    app.exec_()

QMLコード(ファイル名はtest.qmlとして保存):
import QtQuick 2.0
Rectangle {
    id: root
    width: 320; height: 240
    color: "lightgray"
    Text {
        id: txt
        text: "Clicked me"
        font.pixelSize: 20
        anchors.centerIn: parent
    }
    Text {
        id: txt1
        text: "..."
        font.pixelSize: 20
    }
    MouseArea {
        id: mouse_area
        anchors.fill: parent  //     
        onClicked: {
            console.log("test...")  //        
            txt1.text = con.returnValue(20)
        }
    }
}

実行効果は次のとおりです.
マウスをクリックしていない場合:マウスをクリックした後:
QML与Python通信 QML与Python通信
(3)QML接続信号Python
QMLがイベントをトリガすると、Pythonに信号が送信され、Pythonが関数を呼び出す.
まずQMLで信号を定義し、
signal sendClicked(string str) //     

そしてイベントをキャプチャすると信号が送信され、
 MouseArea {
        id: mouse_area
        anchors.fill: parent  //     
        onClicked: {
            root.sendClicked("Hello, Python3")    #      Python
        }
    }

最後にPythonでrootObjectオブジェクトを作成し、このオブジェクトに接続します.
def outputString(string):
    """
      :      
      :      string
       :  
    """
    print(string)
context = view.rootObject()
context.sendClicked.connect(outputString)   #   QML  sendCLicked

以下に完全な例を示します.
この例では、マウスをクリックすると、コンソールが情報を印刷します.
Python 3コード:
# -*- coding: GBK -*-

from PyQt5.QtCore import QUrl, pyqtSlot
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQuick import QQuickView

def outputString(string):
    """
      :      
      :      string
       :  
    """
    print(string)

if __name__ == '__main__':
    path = 'test.qml'   #    QML  

    app = QGuiApplication([])
    view = QQuickView()
    view.engine().quit.connect(app.quit)
    view.setSource(QUrl(path))
    view.show()
    context = view.rootObject()
    context.sendClicked.connect(outputString)   #   QML  sendCLicked
    app.exec_()

QMLコード(ファイル名はtest.qmlとして保存):
import QtQuick 2.0

Rectangle {
    id: root
    width: 320; height: 240
    color: "lightgray"
    signal sendClicked(string str) //     

    Text {
        id: txt
        text: "Clicked me"
        font.pixelSize: 20
        anchors.centerIn: parent
    }
    MouseArea {
        id: mouse_area
        anchors.fill: parent  //     
        onClicked: {
            root.sendClicked("Hello, Python3")    #      Python
        }
    }
}

実行結果は次のとおりです.
QML与Python通信
(4)Python呼び出しQML関数
QMLに関数を作成し、
function updateRotater() {
    rotater.angle += 45
}

PythonでrootObjectオブジェクトを作成し、この関数に接続します.
root = view.rootObject()
timer.timeout.connect(root.updateRotater)

以下に完全な例を示します.
例では、1 sおきにポインタが45°回転します.
Python 3コード:
# -*- coding: GBK -*-

from PyQt5.QtCore import QUrl, QTimer
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQuick import QQuickView

if __name__ == '__main__':
    path = 'test.qml'   #    QML  

    app = QGuiApplication([])
    view = QQuickView()
    view.engine().quit.connect(app.quit)
    view.setSource(QUrl(path))
    view.show()

    timer = QTimer()
    timer.start(2000)
    root = view.rootObject()
    timer.timeout.connect(root.updateRotater)

    app.exec_()

QMLコード(ファイル名はtest.qmlとして保存):
import QtQuick 2.0

Rectangle {
    id: page
    width: 500; height: 200
    color: "lightgray"

    function updateRotater() {
        rotater.angle += 45
    }

    Rectangle {
        id: rotater
        property real angle : 0
        x: 240; y: 95
        width: 100; height: 5
        color: "black"

        transform: Rotation {
            origin.x: 10; origin.y: 5
            angle: rotater.angle
        }
    }
}

実行結果は次のとおりです.
QML与Python通信
私のレベルは限られています.もし漏れがあれば、ご指摘を歓迎します.