python和qml的交互总结和笔记

python和qml混合开发,一般都是python做逻辑,qml做界面,所以大部分都是qml调用python中的逻辑,所以先说最常用的和使用范围最广的。

第一,qml调用python函数

python中的main.py

from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import qmlRegisterType, QQmlApplicationEngine
from PySide2.QtCore import Slot, QObject, QUrl
 
class MyClass(QObject):
    @Slot(int, result=str)  #声明为槽,输入参数为int类型,返回值为str类型
    def returnValue(self, value):
        return str(value+10)

if __name__ == "__main__":
    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()
    engine.load(os.path.join(os.path.dirname(__file__), "main.qml"))
    con = MyClass()
    engine.rootContext().setContextProperty("con",con)

    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(app.exec_())

main.qml

import QtQuick 2.0
 
Window{
    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,此时Python调用一个函数

先在QML中定义一个信号,然后在捕获事件的时候,发射信号。最后Python中创建一个rootObject对象,然后连接这个对象

from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQuick import QQuickView
 
def outputString(string):
    print(string)
 
if __name__ == '__main__':
    path = 'test.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_()
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
        }
    }
}

第三,Python调用QML函数

QML中创建一个函数,Python中创建一个rootObject对象,并连接这个函数

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)   #调用QML函数
    app.exec_()
import QtQuick 2.0
 
Rectangle {
    id: page
    width: 500; height: 200
    color: "lightgray"
 
    function updateRotater() {// 定义函数
        rotater.angle += 5
    }
 
    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
        }
    }
}

第四,python操作qml对象

如何在python里获得qml里的对象?

4.1 获取根对象

使用QQmlApplicationEngine类的rootObjects方法,返回的是一个列表,取索引0即是根对象。

engine = QQmlApplicationEngine() 
engine.load('qml-test.qml') 
root_obj = engine.rootObjects()[0]

这样就会获得id为window的ApplicationWindow对象。

4.2 如何获取任意对象

需要在qml文件中加入objecName属性!暂时还不知道如何获取不是ApplicationWindow下的对象,知道的可以麻烦告知下

QML:

import QtQuick 2.12
import QtQuick.Controls 2.12

ApplicationWindow {
    id: window
    width: 250
    height: 500
    visible: true
    
    Text {
        id: txt
        objectName: "txt"
        text: "Click Me"
        font.pixelSize: 20
        anchors.centerIn: parent
    }
}

Python:

 engine = QQmlApplicationEngine()
 engine.load('qml-test.qml')
 txt_obj = engine.rootObjects()[0].findChild(QObject, "txt")

4.3. 如何在python里读取和设置qml对象的属性和值?

4.3.1 读取对象的属性(如Text对象)

首先通过 findChild 获取Text对象(注意 txt 是qml文件里的 objectName):

txt_obj = engine.rootObjects()[0].findChild(QObject, "txt")
txt_value = txt_obj.property("text")

4.3.2 设置对象的属性

使用setProperty方法可以更改对象的属性值。

txt_obj.setProperty("text""Clicked!")

完整代码:

import sys

from PyQt5.QtCore import QObject
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQml import QQmlApplicationEngine

app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
engine.load('qml-test.qml')

# 根对象
root_obj = engine.rootObjects()[0]
# Text对象
txt_obj = engine.rootObjects()[0].findChild(QObject, "txt")
# 读取属性值
txt_value = txt_obj.property("text")
# 设置属性值
txt_obj.setProperty("text", "Clicked!")

sys.exit(app.exec())

第五,信号/槽机制

把python类注册成qml类,可以直接在qml中使用

qmlRegisterType(CameraOpencv,'MyCamera',1,0,'MyCustomOpenCVItem')
class CameraOpencv(QQuickPaintedItem):
 
   activateVideoChanged = Signal()  #是否开启视频流
    def getVideoState(self):
        return self.activateVideoStream

    def setVideoState(self, state):
        if self.activateVideoStream != state:
            if state == False:
                self._timer1.stop()
            else:
                self._timer1.start(16)
            self.activateVideoStream = state
     activateVideo = Property(bool, fget=getVideoState, fset=setVideoState, notify=activateVideoChanged)

直接在QML中使用

import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.1
import MyCamera 1.0

Item{
    id:root
    property alias myCustomOpenCVItem: myCustomOpenCVItem
    Rectangle{
        color:"black"
        anchors.fill: parent
        MyCustomOpenCVItem{
            id:myCustomOpenCVItem
            objectName:"camera_win"
            anchors.fill:parent
        }
        MouseArea{
            anchors.fill: parent
            onClicked: {
                 content.contentMiddle.myCustomOpenCVItem.save()
            }
        }
    }
}
声明:本内容为作者独立观点,不代表电子星球立场。未经允许不得转载。授权事宜与稿件投诉,请联系:editor@netbroad.com
觉得内容不错的朋友,别忘了一键三连哦!
赞 3
收藏 1
关注 17
成为作者 赚取收益
全部留言
0/200
成为第一个和作者交流的人吧