37. QML的使用

一、什么是QML

  QML,全称为 Qt Meta-Object Language,是一种声明式语言,用于在 Qt 框架中创建用户界面(UI)。QML 是与 HTML 类似的一种标记语言。在 QtQuick 中将由标签组成的元素封装在大括号中 Item{},它采用了 JavaScript 的语法,并通过 Qt 的 QML 引擎来解释和执行 QML 代码。通过 QML,开发者可以快速、简单地创建现代化的用户界面,而无需太多的代码。

  这里,我们新建一个 template.qml 文件,它的内容如下:

import QtQuick 2.5

// Rectangle {}定义了一个矩形(Rectangle)元素。在QML中,元素是通过大括号{}内的属性来配置的。
Rectangle {
    // 设置矩形的宽度和高度绑定到父元素(窗口)的宽度和高度,使其随窗口大小变化
    width: parent.width
    height: parent.height

    color: "lightgray"                      // 设置矩形的颜色

    // 在矩形内部定义一个文本(Text)元素。这意味着文本将作为矩形的一个子元素,通常会被绘制在矩形内部。
    Text {
        text: "hello world!"                // 设置文本元素的内容
        font.pointSize: 24                  // 设置文本的字体大小
        color: "#4A88C7"                    // 设置字体颜色
        // 使用锚点(anchors)系统来定位文本元素,这里将文本元素的中心定位到其父元素的中心
        anchors.centerIn: parent   
    }
}

  然后,我们新建一个 template.py文件,它的内容如下:

import sys

from PySide6.QtWidgets import QApplication
from PySide6.QtCore import QUrl
from PySide6.QtQuick import QQuickView

if __name__ == "__main__":
    # 1.创建一个QApplication类的实例
    app = QApplication(sys.argv)
    # 2.创建QQuickView实例
    view = QQuickView()
    # 3.设置QML源
    view.setSource(QUrl("template.qml"))
    # 4.显示窗口
    view.show()
    # 5.进入程序的主循环并通过exit()函数确保主循环安全结束
    sys.exit(app.exec())

二、执行JavaScript代码

  我们可以在 QML 组件的信号处理器中编写 JavaScript 代码。

import QtQuick 2.5
import QtQuick.Controls 2.15

// Rectangle {}定义了一个矩形(Rectangle)元素。在QML中,元素是通过大括号{}内的属性来配置的。
Rectangle {
    // 设置矩形的宽度和高度绑定到父元素(窗口)的宽度和高度,使其随窗口大小变化
    width: parent.width
    height: parent.height
    color: "lightblue"                                          // 背景颜色

    // 在矩形内部定义一个文本(Text)元素。这意味着文本将作为矩形的一个子元素,通常会被绘制在矩形内部。
    Text {
        id: click_text                                          // 定义一个标识
        text: "当前点击次数:0"                                  // 设置文本元素的内容
        font.pointSize: 24                                      // 设置文本的字体大小
        color: "#4A88C7"                                        // 设置字体颜色

        // 使用锚点(anchors)系统来定位文本元素
        anchors.top: parent.top                                 // 将顶部的锚点定位到父元素的顶部
        anchors.horizontalCenter: parent.horizontalCenter       // 水平居中
        anchors.topMargin: 20                                   // 设置顶部边距为20像素
    }

    Button {
        id: click_button
        text: "点我,修改背景色"
        width: 200
        height: 50
  
        palette.buttonText: "#FF99CC"                           // 修改文字颜色

        //背景颜色
        background: Rectangle{
            border.color: "#FFF0F5"                             // 边框颜色
            border.width: 1                                     // 边框宽度
            color: "#F8F8FF"                                    // 背景颜色
        }

        // 使用锚点(anchors)系统来定位文本元素
        anchors.centerIn: parent                                // 将中心的锚点定位到父元素的中心

        property int click_count: 0                             // 定义一个属性记录点击次数

        // 按键点击时执行,这里可以直接执行JS代码
        onClicked: {
            click_count += 1                                    // 更新点击次数
            click_text.text = "当前点击次数:" + click_count     // 修改标签文本
            // 随机生成背景颜色
            parent.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
        }
    }
}

三、定时器

  QML 有一个 Timer元素,它允许你在 QML 中设置定时器。这个元素是 Qt Quick 模块的一部分。我们可以通过定时器的 interval 属性设置 定时间隔,通过 running 属性设置 定时器默认是否运行,通过 repeat 属性设置 定时器是否可以重复触发。在设置完相关属性后,我们还可以通过 start() 开发 启动定时器,通过 stop() 方法 停止定时器

import QtQuick 2.5
import QtQuick.Controls 2.15

// Rectangle {}定义了一个矩形(Rectangle)元素。在QML中,元素是通过大括号{}内的属性来配置的。
Rectangle {
    // 设置矩形的宽度和高度绑定到父元素(窗口)的宽度和高度,使其随窗口大小变化
    width: parent.width
    height: parent.height
    color: "lightblue"                                          // 背景颜色

    // 定义一个进度条
    ProgressBar {
        id: progressBar                                         // 定义一个标识
        width: 500
        height: 20

        anchors.centerIn: parent                                // 将中心的锚点位到父元素的中心

        from: 0                                                 // 设置进度条的最小值
        to: 100                                                 // 设置进度条的最大值
        value: 30                                               // 设置当前值
    }

    // 在矩形内部定义一个文本(Text)元素。这意味着文本将作为矩形的一个子元素,通常会被绘制在矩形内部。
    Text {
        id: progressBar_text                                    // 定义一个标识
        text: "Value:" + progressBar.value                     // 设置文本元素的内容
        font.pointSize: 24                                      // 设置文本的字体大小
        color: "#4A88C7"                                        // 设置字体颜色

        // 使用锚点(anchors)系统来定位文本元素
        anchors.top: parent.top                                 // 将顶部的锚点定位到父元素的顶部
        anchors.horizontalCenter: parent.horizontalCenter       // 水平居中
        anchors.topMargin: 20                                   // 设置顶部边距为20像素
    }

    // 定义一个按钮
    Button{
        id: start_button
        text: "开始加载"                                        // 按键文本
        width: 200
        height: 50

        // 使用锚点(anchors)系统来定位文本元素
        anchors.left: parent.left                               // 将左边的锚点定位到父元素的左边
        anchors.leftMargin: 20                                  // 设置左侧边距为20像素
        anchors.bottom: parent.bottom                           // 将底部的锚点定位到父元素的底部
        anchors.bottomMargin: 20                                // 设置底部边距为20像素

        // 按键点击时触发
        onClicked: {
            if (start_button.text == "开始加载") {
                timer.start()
                start_button.text = "暂停加载"
            } else if (start_button.text == "重新加载") {
                progressBar.value = 0
                timer.start()
                start_button.text = "暂停加载"
            } else if (start_button.text == "暂停加载") {
                timer.stop()
                start_button.text = "继续加载"
            } else if (start_button.text == "继续加载") {
                timer.start()
                start_button.text = "暂停加载"
            }
        }
    }

    Button{
        id: reset_button
        text: "重置"                                            // 按键文本
        width: 200
        height: 50

        anchors.right: parent.right                             // 将右边的锚点定位到父元素的右边
        anchors.rightMargin: 20                                 // 设置右侧边距为20像素
        anchors.bottom: parent.bottom                           // 将底部的锚点定位到父元素的底部
        anchors.bottomMargin: 20                                // 设置底部边距为20像素

        // 按键点击时触发
        onClicked: {
            progressBar.value = 0
        }
    }

    // 定义一个定时器
    Timer{
        id: timer                                               // 定义一个标识
        interval: 100                                           // 定义定时器间隔
        running: false                                          // 定时器默认不运行
        repeat: true                                            // 定时器是否可以重复触发

        // 当定时器触发时执行
        onTriggered: {
            var value = progressBar.value + 1                   // 计算新的计数值
            if (value > 100) {
                timer.stop()                                    // 如果进度值超过最大值,停止定时器
                start_button.text = "重新加载"
            } else {
                progressBar.value = value                       // 更新进度条器的值
                progressBar_text.text = "Value:" + value        // 更新显示文本
            }
        }
    }
}

四、布局

  在 QML(Qt Modeling Language)中,布局管理是通过一系列布局元素来实现的,这些元素负责在 QML 界面中组织和排列子元素。QML 提供了几种内置的布局类型,如 RowLayout(水平布局)、ColumnLayout(垂直布局)、GridLayout(网格布局)等,它们允许你以不同的方式排列和组织子元素。

4.1、锚点

  在 QML 中,锚点(anchors)是一种用于定义元素之间相对位置和大小关系的机制。锚点允许你指定一个元素相对于其父元素或其他元素的位置和尺寸。通过使用锚点,你可以创建响应式布局,使 QML 界面能够根据不同屏幕尺寸和分辨率进行自适应调整。

  QML 中的每个元素都有一个隐式的锚点系统,你可以通过 anchors 属性来访问它。anchors 属性提供了多个属性来设置锚点的位置,包括:

  • anchors.left:将元素的左边缘锚定到某个参考点的左边缘。
  • anchors.right:将元素的右边缘锚定到某个参考点的右边缘。
  • anchors.top:将元素的顶部边缘锚定到某个参考点的顶部边缘。
  • anchors.bottom:将元素的底部边缘锚定到某个参考点的底部边缘。
  • anchors.horizontalCenter:将元素的水平中心锚定到某个参考点的水平中心。
  • anchors.verticalCenter:将元素的垂直中心锚定到某个参考点的垂直中心。
  • anchors.fill:使元素填充其父元素或参考元素的整个区域。
  • anchors.margins:设置元素与其锚点之间的外边距。
  • anchors.leftMargin:设置元素与其锚点之间的左边距。
  • anchors.rightMargin:设置元素与其锚点之间的右边距。
  • anchors.topMargin:设置元素与其锚点之间的顶边距。
  • anchors.bottomMargin:设置元素与其锚点之间的底边距。
import QtQuick 2.5
import QtQuick.Controls 2.15

// Rectangle {}定义了一个矩形(Rectangle)元素。在QML中,元素是通过大括号{}内的属性来配置的。
Rectangle {
    // 设置矩形的宽度和高度绑定到父元素(窗口)的宽度和高度,使其随窗口大小变化
    width: parent.width
    height: parent.height
    color: "lightblue"                                          // 背景颜色

    // 在矩形内部定义一个文本(Text)元素。这意味着文本将作为矩形的一个子元素,通常会被绘制在矩形内部。
    Text {
        id: title_text                                          // 定义一个标识
        text: "Custom Layout Example"                           // 设置文本元素的内容
        font.pointSize: 24                                      // 设置文本的字体大小
        color: "#4A88C7"                                        // 设置字体颜色

        // 使用锚点(anchors)系统来定位文本元素
        anchors.top: parent.top                                 // 将顶部的锚点定位到父元素的顶部
        anchors.horizontalCenter: parent.horizontalCenter       // 水平居中
        anchors.topMargin: 20                                   // 设置顶部边距为20像素
    }

    // 在矩形内部定义一个文本(Text)元素。这意味着文本将作为矩形的一个子元素,通常会被绘制在矩形内部。
    Text {
        id: content_text                                        // 定义一个标识
        text: "This is an exmaple of using anchors for layout." // 设置文本元素的内容
        font.pointSize: 18                                      // 设置文本的字体大小
        color: "#FF99CC"                                        // 设置字体颜色

        // 使用锚点(anchors)系统来定位文本元素
        anchors.top: title_text.bottom                          // 将顶部的锚点定位到指定控件父的底部
        anchors.horizontalCenter: parent.horizontalCenter       // 水平居中
        anchors.topMargin: 20                                   // 设置顶部边距为20像素
    }

    // 定义一个按钮
    Button{
        id: center_button
        text: "center button"                                   // 按键文本
        width: 100
        height: 50

        // 使用锚点(anchors)系统来定位文本元素,这里中心的锚点定位到其父元素的中心
        anchors.centerIn: parent
    }

    Button{
        id: left_button
        text: "left button"                                     // 按键文本
        width: 100
        height: 50

        // 使用锚点(anchors)系统来定位文本元素
        anchors.left: parent.left                               // 将左侧的锚点定位到父元素的左侧
        anchors.leftMargin: 20                                  // 设置左侧边距为20像素
        anchors.bottom: parent.bottom                           // 将底部的锚点定位到父元素的底部
        anchors.bottomMargin: 20                                // 设置底部边距为20像素
    }

    Button{
        id: right_button
        text: "right button"                                    // 按键文本
        width: 100
        height: 50

        anchors.right: parent.right                             // 将右侧的锚点定位到父元素的右侧
        anchors.rightMargin: 20                                 // 设置右侧边距为20像素
        anchors.bottom: parent.bottom                           // 将底部的锚点定位到父元素的底部
        anchors.bottomMargin: 20                                // 设置底部边距为20像素
    }
}

当你使用锚点时,请确保你指定的参考点(如父元素或其他元素)是有效的,并且它们在布局中是可见的。

锚点系统是基于父元素或参考元素的坐标系统来工作的,因此如果父元素或参考元素的大小或位置发生变化,依赖于它们的子元素也会相应地发生变化。

在使用锚点时,要注意避免循环依赖或相互冲突的锚点设置,这可能会导致布局问题或不可预测的行为。

4.2、水平布局

  在 QML 中,水平布局通常是通过 RowLayout 来实现的。RowLayout 是一种布局管理器,它允许你将子元素水平地排列在一行中。

import QtQuick 2.5
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15

// Rectangle {}定义了一个矩形(Rectangle)元素。在QML中,元素是通过大括号{}内的属性来配置的。
Rectangle {
    // 设置矩形的宽度和高度绑定到父元素(窗口)的宽度和高度,使其随窗口大小变化
    width: parent.width
    height: parent.height
    color: "lightblue"                                          // 背景颜色

    // 定义一个RowLayout,用于水平布局
    RowLayout{
        id: rowLayout
        anchors.centerIn: parent                                // 将中心的锚点定位到父元素的中心
        spacing: 10                                             // 用于设置子元素之间的间隔

        // 第一个按钮
        Button{
            id: left_button
            text: "left button"                                 // 按键文本
            width: 100
            height: 50
        }

        Button{
            id: center_button
            text: "center button"                                 // 按键文本
            width: 100
            height: 50
        }

        Button{
            id: right_button
            text: "right button"                                 // 按键文本
            width: 100
            height: 50
        }
    }
}

4.3、垂直布局

  在 QML 中,垂直布局通常是通过 ColumnLayoutColumn 来实现的。这些布局管理器允许你将子元素垂直地排列在一起。

import QtQuick 2.5
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15

// Rectangle {}定义了一个矩形(Rectangle)元素。在QML中,元素是通过大括号{}内的属性来配置的。
Rectangle {
    // 设置矩形的宽度和高度绑定到父元素(窗口)的宽度和高度,使其随窗口大小变化
    width: parent.width
    height: parent.height
    color: "lightblue"                                          // 背景颜色

    // 定义一个ColumnLayout,用于垂直布局
    ColumnLayout{
        id: columnLayout
        anchors.centerIn: parent                                // 将中心的锚点定位到父元素的中心
        spacing: 10                                             // 用于设置子元素之间的间隔
        width: parent.width * 0.8
        height: parent.height * 0.8

        // 第一个按钮
        Button{
            id: top_button
            text: "top button"                                  // 按键文本
            Layout.fillWidth: true                              // 设置按钮填充Column布局的宽度
            Layout.fillHeight: true                             // 设置按钮填充Column布局的高度
        }

        Button{
            id: center_button
            text: "center button"                                 // 按键文本
            Layout.fillWidth: true                              // 设置按钮填充Column布局的宽度
            Layout.fillHeight: true                             // 设置按钮填充Column布局的高度
        }

        Button{
            id: bottom_button
            text: "bottom button"                                 // 按键文本
            Layout.fillWidth: true                              // 设置按钮填充Column布局的宽度
            Layout.fillHeight: true                             // 设置按钮填充Column布局的高度
        }
    }
}

4.4、网格布局

  在 QML 中,网格布局是通过 GridLayout 来实现的。GridLayout 允许你将子元素放置在一个二维的网格中,并且可以指定网格的行数和列数,并控制每个元素在网格中的位置、大小和跨越多个单元格的能力。

import QtQuick 2.5
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15

// Rectangle {}定义了一个矩形(Rectangle)元素。在QML中,元素是通过大括号{}内的属性来配置的。
Rectangle {
    // 设置矩形的宽度和高度绑定到父元素(窗口)的宽度和高度,使其随窗口大小变化
    width: parent.width
    height: parent.height
    color: "lightblue"                                          // 背景颜色

    // 定义一个GridLayout,用于网格布局
    GridLayout{
        id: gridLayout
        anchors.centerIn: parent                                // 将中心的锚点定位到父元素的中心
        rows: 3                                                 // 设置行数
        columns: 3                                              // 设置列数
        rowSpacing: 10                                          // 设置行间距
        columnSpacing: 10                                       // 设置列间距
        width: parent.width * 0.8
        height: parent.height * 0.8

        // 第一个按钮
        Button{
            id: button1
            text: "button 1"                                    // 按键文本
            Layout.row: 0                                       // 设置按键所在的行
            Layout.column: 0                                    // 设置按键所在的列
            Layout.fillWidth: true                              // 设置按钮填充Column布局的宽度
            Layout.fillHeight: true                             // 设置按钮填充Column布局的高度
        }

        Button{
            id: button2
            text: "button 2"                                    // 按键文本
            Layout.row: 0                                       // 设置按键所在的行
            Layout.column: 1                                    // 设置按键所在的列
            Layout.fillWidth: true                              // 设置按钮填充Column布局的宽度
            Layout.fillHeight: true                             // 设置按钮填充Column布局的高度
        }

        Button{
            id: button3
            text: "button 3"                                    // 按键文本
            Layout.row: 0                                       // 设置按键所在的行
            Layout.column: 2                                    // 设置按键所在的列
            Layout.fillWidth: true                              // 设置按钮填充Column布局的宽度
            Layout.fillHeight: true                             // 设置按钮填充Column布局的高度
        }

        Button{
            id: button4
            text: "button 4"                                    // 按键文本
            Layout.row: 1                                       // 设置按键所在的行
            Layout.column: 0                                    // 设置按键所在的列
            Layout.fillWidth: true                              // 设置按钮填充Column布局的宽度
            Layout.fillHeight: true                             // 设置按钮填充Column布局的高度
            Layout.rowSpan: 2                                   // 合并两行
        }

        Button{
            id: button5
            text: "button 5"                                    // 按键文本
            Layout.row: 1                                       // 设置按键所在的行
            Layout.column: 1                                    // 设置按键所在的列
            Layout.fillWidth: true                              // 设置按钮填充Column布局的宽度
            Layout.fillHeight: true                             // 设置按钮填充Column布局的高度
        }

        Button{
            id: button6
            text: "button 6"                                    // 按键文本
            Layout.row: 1                                       // 设置按键所在的行
            Layout.column: 2                                    // 设置按键所在的列
            Layout.fillWidth: true                              // 设置按钮填充Column布局的宽度
            Layout.fillHeight: true                             // 设置按钮填充Column布局的高度
        }

        Button{
            id: button7
            text: "button 7"                                    // 按键文本
            Layout.row: 2                                       // 设置按键所在的行
            Layout.column: 1                                    // 设置按键所在的列
            Layout.fillWidth: true                              // 设置按钮填充Column布局的宽度
            Layout.fillHeight: true                             // 设置按钮填充Column布局的高度
            Layout.columnSpan: 2                                // 合并两列
        }
    }
}

4.5、流式布局

  在 QML 中,流式布局(Flow Layout)是一种非常灵活的布局方式,它允许元素根据容器的尺寸和元素的尺寸自动进行排列。流式布局类似于文本排版中的“流”概念,元素会按照指定的方向(通常是水平或垂直)依次排列,当一行或一列无法容纳更多元素时,会自动换行或换列。

  QML 中的流式布局是通过 Flow 定位器来实现的。Flow 定位器允许你以声明式的方式将元素组织成流式布局形式,你可以通过 spacing 属性来设置元素之间的间距,通过 flow 属性来指定布局的方向(从左到右、从右到左、从上到下、从下到上)。

import QtQuick 2.5
import QtQuick.Controls 2.15

// Rectangle {}定义了一个矩形(Rectangle)元素。在QML中,元素是通过大括号{}内的属性来配置的。
Rectangle {
    // 设置矩形的宽度和高度绑定到父元素(窗口)的宽度和高度,使其随窗口大小变化
    width: parent.width
    height: parent.height
    color: "lightblue"                                          // 背景颜色

    // 定义一个Flow,用于流式布局
    Flow{
        id: flowLayout
        anchors.centerIn: parent                                // 将中心的锚点定位到父元素的中心
        width: parent.width * 0.8
        height: parent.height * 0.8
        spacing: 10

        // Repeater是一个用于根据模型(通常是列表或数组)动态生成一组子元素的有用工具
        Repeater{
            // 定义了数据源,通常是一个列表或数组。
            model: 18                                           // 设置重读的次数
            // 定义了如何显示模型中的每个项目,它是一个包含要实例化的 QML 元素的组件。
            delegate: Button{
                text: "button " + (index + 1)
                width: 100
                height: 50
            }
        }
    }
}

五、信号与槽

  在 QML 中,信号与槽机制是对象间通信的一种重要方式。它允许对象在其状态改变或发生特定事件时通知其他对象,并触发相应的处理函数。

  信号是对象发出的通知,表明某个事件已经发生。信号可以有参数,并且不返回任何值。在 QML 中,信号是通过在 QML 类型中声明 signal 关键字来定义的。

  槽是响应信号的处理函数。当信号被发出时,与之连接的槽函数会被调用。在 QML 中,槽可以是 QML 中的函数,也可以是 Python 中定义的槽函数(通过 Qt 的元对象系统暴露给 QML)。

  在 QML 中,可以使用 connect 函数来连接信号与槽。

  QML 发送信号给 Python 的流程如下:

  1. 在 QML 中定义一个信号 signal print_text_signal()
  2. 在 Python 中使用 @Slot 装饰槽函数 print_text()
  3. 在 Python 中创建 QQuickView 实例 view = QQuickView()
  4. 在 Python 中通过 view.setSource(QUrl("template.qml")) 加载 QML。
  5. 在 Python 中通过 root_object = view.rootObject() 获取QML文档的根对象。
  6. 在 Python 中通过 root_object.print_text_signal.connect(print_text) 绑定信号与槽。
  7. 在 QML 中触发信号 print_text_signal()
import QtQuick 2.5
import QtQuick.Controls 2.15

// Rectangle {}定义了一个矩形(Rectangle)元素。在QML中,元素是通过大括号{}内的属性来配置的。
Rectangle {
    // 设置矩形的宽度和高度绑定到父元素(窗口)的宽度和高度,使其随窗口大小变化
    width: parent.width
    height: parent.height
    color: "lightblue"                                          // 背景颜色

    // 定义信号
    signal print_text_signal(string text)

    Text{
        id: text
        anchors.top: parent.top
    }

    Button{
        id: button
        text: "print_text"                                 // 按键文本
        width: 100
        height: 50
        anchors.centerIn: parent

        onClicked: {
            // 触发信号
            print_text_signal("Hello Sakura!")
        }
    }
}
import sys

from PySide6.QtWidgets import QApplication
from PySide6.QtCore import QUrl
from PySide6.QtQuick import QQuickView
from PySide6.QtCore import Slot

# 使用@Slot装饰器将my_printer函数标记为槽函数
@Slot(str)
def print_text(text):
    print(text)

if __name__ == "__main__":
    # 1.创建一个QApplication类的实例
    app = QApplication(sys.argv)
    # 2.创建QQuickView实例
    view = QQuickView()
    # 3.设置QML源
    view.setSource(QUrl("template.qml"))
    # 4.设置QQuickView窗口的默认宽度和高度
    view.resize(600, 400)
    # 5.显示窗口
    view.show()
    # 6.获取QML文档的根对象
    root_object = view.rootObject()
    # 7.将信号与槽函数绑定
    root_object.print_text_signal.connect(print_text)
    # 8.进入程序的主循环并通过exit()函数确保主循环安全结束
    sys.exit(app.exec())

  Python 发送信号给 QML 的流程如下:

  1. 在 Python 中定义一个类 MySignal 继承 QObject,在该类中定义一个信号 update_text_signal = Signal()
  2. 在 Python 中创建 QQuickView 实例 view = QQuickView()
  3. 在 Python 中通过 engine = view.engine() 获取 QQuickView 的引擎。
  4. 在 Python 中通过 content = engine.rootContext() 获取引擎的上下文。
  5. 在 Python 中创建信号对象 mySignal = MySignal()
  6. 在 Python 通过 content.setContextProperty("mySignal", mySignal) 设置上下文属性。
  7. 在 QML 中定义一个槽函数 function mySlot()
  8. 在 QML 中绑定信号与槽 mySignal.updata_text_signal.connect(mySlot)
  9. 在 Python 中触发信号 mySignal.updata_text_signal.emit("Hello Sakura!")
import QtQuick 2.5
import QtQuick.Controls 2.15

// Rectangle {}定义了一个矩形(Rectangle)元素。在QML中,元素是通过大括号{}内的属性来配置的。
Rectangle {
    // 设置矩形的宽度和高度绑定到父元素(窗口)的宽度和高度,使其随窗口大小变化
    width: parent.width
    height: parent.height
    color: "lightblue"                                          // 背景颜色

    // 定义信号
    signal button_clicked_signal()

    Text{
        id: show_text
        font.pointSize: 24                  // 设置文本的字体大小
        color: "#4A88C7"                    // 设置字体颜色
        anchors.top: parent.top
        anchors.horizontalCenter: parent.horizontalCenter       // 水平居中
        anchors.topMargin: 20                                   // 设置顶部边距为20像素
    }

    Button{
        id: button
        text: "print_text"                                 // 按键文本
        width: 100
        height: 50
        anchors.centerIn: parent

        onClicked: {
            // 触发信号
            button_clicked_signal()
        }
    }

    // 定义组件完成后的处理函数
    Component.onCompleted: function () {
        // 绑定Python中
        mySignal.updata_text_signal.connect(mySlot)
    }

    // 定义一个槽函数
    function mySlot(text){
        show_text.text = text
    }
}
import sys

from PySide6.QtWidgets import QApplication
from PySide6.QtCore import QUrl
from PySide6.QtQuick import QQuickView
from PySide6.QtCore import Slot, QObject, Signal

# 创建一个类继承自QObject
class MySignal(QObject):
    # 定义一个信号
    updata_text_signal = Signal(str)

# 使用@Slot装饰器将my_printer函数标记为槽函数
@Slot()
def button_clicked():
    mySignal.updata_text_signal.emit("Hello Sakura!")

if __name__ == "__main__":
    # 1.创建一个QApplication类的实例
    app = QApplication(sys.argv)
    # 2.创建QQuickView实例
    view = QQuickView()
    # 3.获取QQuickView的引擎
    engine = view.engine()
    # 4.获取引擎的上下文
    content = engine.rootContext()
    # 5.创建一个MySignal类的实例
    mySignal = MySignal()
    # 6.设置属性上下文
    content.setContextProperty("mySignal", mySignal)
    # 7.设置QML源
    view.setSource(QUrl("template.qml"))
    # 8.设置QQuickView窗口的默认宽度和高度
    view.resize(600, 400)
    # 9.显示窗口
    view.show()
    # 10.获取QML文档的根对象
    root_object = view.rootObject()
    # 11.将信号与槽函数绑定
    root_object.button_clicked_signal.connect(button_clicked)
    # 12.进入程序的主循环并通过exit()函数确保主循环安全结束
    sys.exit(app.exec())
posted @   星光映梦  阅读(62)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
历史上的今天:
2024-01-25 49. CAN通信协议
点击右上角即可分享
微信分享提示