QML與Python通訊

    對於Python3和QML通訊,實際上就是PyQt5+QML+Python3混合編程,這是必須的,由於QML作圖形界面比較容易,可是作功能實現就用Python比較好,雖然QML也能嵌入JavaScript代碼進行實現,可是這樣話還不如用Python來實現,代碼簡潔、易懂。html

    對於如下的例子,參考了以下的鏈接:python

Connecting QML signals in PySide:編程

http://qt-project.org/wiki/Connecting_QML_Signals_in_PySide app

PyQt 5.1.1 Reference Guide -> Support for Signals and Slots:ide

http://pyqt.sourceforge.net/Docs/PyQt5/signals_slots.html?highlight=pyqtslot#PyQt5.QtCore.pyqtSlot函數

(1)QML顯式的調用Python函數
ui

定義一個類,並繼承QtCore.QObject對象,並使用@修飾符修飾pyqtSlotspa

class MyClass(QObject):
    @pyqtSlot(str)    # 傳遞參數類型字符串
    def outputString(self, string):
        """
        功能: 建立一個槽
        參數: 輸出的數據string
        返回值: 無
        """
        print(string)

建立rootContext對象,並使用setContextProperty(string, object)註冊對象,這樣在QML中就能夠調用這個函數了。.net

context = view.rootContext()
context.setContextProperty("con", con)

以下是一個完整的例子:指針

這個例子運行後,若是點擊鼠標的話,會在控制檯打印字符串。

Python3代碼:

# -*- 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")
        }
    }
}

運行結果以下:

(2)QML調用Python函數,並返回

這個例子跟上一個相相似,只是此次調用Python的函數具備返回值功能。

如下是一個完整的例子:

運行程序後,點擊鼠標,左上角會顯示數字30。

Python3代碼:

# -*- 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)
        }
    }
}

運行效果以下:

未點擊鼠標時:                                                              點擊鼠標以後:


(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

如下是一個完整的例子:

這個例子中,當點擊鼠標的時候,控制檯會打印信息。

Python3代碼:

# -*- 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
        }
    }
}

運行結果以下:


(4)Python調用QML函數

QML中建立一個函數,

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

Python中建立一個rootObject對象,並鏈接這個函數,

root = view.rootObject()
timer.timeout.connect(root.updateRotater)

如下是一個完整的例子:

例子中,每隔1s,指針會旋轉45°。

Python3代碼:

# -*- 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
        }
    }
}

運行結果以下: 


本人水平有限,若是有疏漏之處,歡迎指點。

相關文章
相關標籤/搜索