Qt第十六章:QWidget与QML混合开发

目录

一、Qml作为窗口引入

二、Qml作为控件引入(Qml根组件不能是window)

三、两个问题①Qml文件如何调用python函数②python代码如何控制Qml元素。


一、Qml作为窗口引入

例:QWidget窗口中用按钮打开和关闭Qml窗口
①QWidget窗口

import sys
from pathlib import Path

from PySide6.QtCore import QObject, Slot
from PySide6.QtQml import QQmlApplicationEngine
from PySide6.QtQuick import QQuickItem
from PySide6.QtWidgets import QApplication, QWidget, QPushButton

class TestWidget(QWidget):
    def __init__(self, parent=None):
        super(TestWidget, self).__init__(parent)
        self.button_open = QPushButton(self)
        self.button_open.setText("打开Qml窗口")
        self.button_open.setGeometry(0, 100, 100, 50)
        self.button_open.clicked.connect(self.handle_button_open_click)
        self.button_close = QPushButton(self)
        self.button_close.setText("关闭Qml窗口")
        self.button_close.setGeometry(100, 100, 100, 50)
        self.button_close.clicked.connect(self.handle_button_close_click)

    # 打开Qml窗口
    def handle_button_open_click(self):
        self.widget = LoginQuickWidget()

    # 关闭Qml窗口
    def handle_button_close_click(self):
        if hasattr(self, 'widget') and self.widget:
            del self.widget


if __name__ == '__main__':
    app = QApplication([])
    widget = TestWidget()
    widget.show()
    app.exec()

②Qml窗口

注意:此处是直接引入qml文件。如果是从qrc资源文件中引入qml,则直接QQmlApplicationEngine.load即可
 ​​​​​​​

# 槽函数类(一个承载槽函数的容器类)
class Slots(QObject):
    def __init__(self, objects):
        self.objects = objects
        super().__init__()

    @Slot(str, result=None)
    def set_text_msg(self, msg):
        # 获取qml中的Text对象
        child = self.objects[0].findChild(QQuickItem, "text1")
        # 获取对象属性
        p = child.property("text")
        # 设置对象属性
        child.setProperty("text", p + msg)

    @Slot(result=str)
    def get_text_msg(self):
        return "皎氯"


"""
这种方式是以Qml作为窗口来使用。所有的逻辑UI都由Qml来完成。python提供可以调用数据的API即可。
"""


class LoginQuickWidget:
    def __init__(self):
        # 初始化UI
        self.engine = QQmlApplicationEngine()
        qml_file = Path(__file__).resolve().parent / "login.qml"
        # 加载qml文件
        self.engine.load(qml_file)
        if not self.engine.rootObjects():
            sys.exit(-1)
        # qml对象集合
        objects = self.engine.rootObjects()
        # 实例化槽函数
        self.slots = Slots(objects)
        # 注入槽函数
        self.engine.rootContext().setContextProperty('slots', self.slots)

③Qml文件

/**************************QML文件**************************/

import QtQuick
import QtQuick.Window
import QtQuick.Controls 6.3
import QtQuick.Layouts 6.3
import QtQuick.Controls.Windows 6.0

//主窗口
Window {
    width: 800
    height: 400
    visible: true
    title: qsTr("测试窗口")
    Image {
        id:background_image
        anchors.fill: parent
        fillMode: Image.PreserveAspectCrop
        source: "http://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg"
        antialiasing: true
    }
    //文本展示框
    Text {
        id: text1
        //用于python获取此对象
        objectName:"text1"
        x: 300
        y: 20
        width: 200
        height: 34
        text: qsTr("初始值")
        font.pixelSize: 12
    }

    //一:通过JavaScript控制UI逻辑
    Button {
        id: button
        x: 125
        y: 179
        width: 125
        height: 29
        text: qsTr("调用JavaScript方法")
        //点击事件
        onClicked: {
            change()
        }
        //JavaScript函数
        function change(){
            var date = new Date();
            text1.text=qsTr(date.getFullYear()+"年"+(date.getMonth() + 1)+"月"+date.getDate()+"日"+date.getHours()+"时"+date.getMinutes()+"分"+date.getSeconds()+"秒")
        }
    }

    //二:通过Python控制UI逻辑(不推荐,因为要做UI与业务逻辑分离;槽函数相当于于ajax请求来获取数据,而不是去控制UI本身)
    Button {
        id: button1
        x: 325
        y: 179
        width: 125
        height: 29
        text: qsTr("调用Python设置属性")
        //点击事件
        onClicked: {
            //调用注入的槽函数,使用槽函数改变视图
            slots.set_text_msg("小小改变")
        }
    }

    //三:通过Python获取数据,JavaScript渲染UI(推荐方式)
    Button {
        id: button2
        x: 525
        y: 179
        width: 125
        height: 29
        text: qsTr("调用Python获取数据")
        //点击事件
        onClicked: {
            //调用注入的槽函数,使用槽函数获取数据
            var msg=slots.get_text_msg()
            //利用JS进行渲染
            text1.text=qsTr(msg)
        }
    }

}

二、Qml作为控件引入(Qml根组件不能是window)

from PySide6.QtCore import QUrl, Slot, QObject
from PySide6.QtQuick import QQuickItem
from PySide6.QtQuickWidgets import QQuickWidget
from PySide6.QtWidgets import QWidget, QApplication, QVBoxLayout, QPushButton


# 槽函数类(一个承载槽函数的容器类)
class Slots(QObject):
    def __init__(self, obj):
        super(Slots, self).__init__()
        self.obj = obj

    @Slot(str, result=None)
    def set_text_msg(self, msg):
        # 获取qml中的Text对象
        child = self.obj.findChild(QQuickItem, "text1")
        # 获取对象属性
        p = child.property("text")
        # 设置对象属性
        child.setProperty("text", p + msg)

    @Slot(result=str)
    def get_text_msg(self):
        return "皎氯"


class TestQWidget(QWidget):

    def __init__(self, parent=None):
        super(TestQWidget, self).__init__(parent)
        self.resize(800, 300)
        # 垂直布局
        self.layout = QVBoxLayout(self)
        # OK按钮
        self.button = QPushButton("OK")
        self.button.clicked.connect(lambda: print("OK"))
        self.layout.addWidget(self.button)

        # QML控件
        self.qml_widget = QQuickWidget()
        # 设置缩放模式
        self.qml_widget.setResizeMode(QQuickWidget.ResizeMode.SizeRootObjectToView)
        # 向QML中传入数据(必须在setSource之前传入)
        self.qml_widget.rootContext().setContextProperty("obj", '张良')
        self.qml_widget.setSource(QUrl("test2.qml"))
        # 获取QML中的对象(必须在setSource之后)
        self.root_object: QQuickItem = self.qml_widget.rootObject()
        # 实例化槽函数
        self.slots = Slots(self.root_object)
        # 注入槽函数
        self.qml_widget.rootContext().setContextProperty('slots', self.slots)

        # 获取对象
        child: QQuickItem = self.root_object.findChild(QQuickItem, "text1")
        # 获取对象属性
        print(child.property("text"))
        
        # 加入布局
        self.layout.addWidget(self.qml_widget)


if __name__ == '__main__':
    app = QApplication([])
    widget = TestQWidget()
    widget.show()
    app.exec()
import QtQuick
import QtQuick.Window
import QtQuick.Controls 6.3
import QtQuick.Layouts 6.3
import QtQuick.Controls.Windows 6.0


Rectangle {
    id:root
    color: "yellow"
    radius:10
    //背景图
    Image {
        id:background_image
        anchors.fill: parent
        fillMode: Image.PreserveAspectCrop
        source: "http://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg"
        antialiasing: true
    }
    //文本展示框
    Text {
        id: text1
        //用于python获取此对象
        objectName:"text1"
        x: 300
        y: 20
        width: 200
        height: 34
        text: qsTr(obj)
        font.pixelSize: 12
    }

    //一:通过JavaScript控制UI逻辑
    Button {
        id: button
        x: 125
        y: 179
        width: 125
        height: 29
        text: qsTr("调用JavaScript方法")
        //点击事件
        onClicked: {
            change()
        }
        //JavaScript函数
        function change(){
            var date = new Date();
            text1.text=qsTr(date.getFullYear()+"年"+(date.getMonth() + 1)+"月"+date.getDate()+"日"+date.getHours()+"时"+date.getMinutes()+"分"+date.getSeconds()+"秒")
        }
    }

    //二:通过Python控制UI逻辑(不推荐,因为要做UI与业务逻辑分离;槽函数相当于于ajax请求来获取数据,而不是去控制UI本身)
    Button {
        id: button1
        x: 325
        y: 179
        width: 125
        height: 29
        text: qsTr("调用Python设置属性")
        //点击事件
        onClicked: {
            //调用注入的槽函数,使用槽函数改变视图
            slots.set_text_msg("小小改变")
        }
    }

    //三:通过Python获取数据,JavaScript渲染UI(推荐方式)
    Button {
        id: button2
        x: 525
        y: 179
        width: 125
        height: 29
        text: qsTr("调用Python获取数据")
        //点击事件
        onClicked: {
            //调用注入的槽函数,使用槽函数获取数据
            var msg=slots.get_text_msg()
            //利用JS进行渲染
            text1.text=qsTr(msg)
        }
    }

}

三、3个问题①Qml文件如何调用python函数②python代码如何控制Qml元素。③python如何执行Qml中的函数。

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

文子阳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值