当前位置: 首页 > news >正文

07. 自定义组件

一、在单独文件中自定义组件

  我们可以在终端中使用 pip 安装 PySide6 模块。默认是从国外的主站上下载,因此,我们可能会遇到网络不好的情况导致下载失败。我们可以在 pip 指令后通过 -i 指定国内镜像源下载

pip install pyside6 -i https://mirrors.aliyun.com/pypi/simple

  国内常用的 pip 下载源列表:

  • 阿里云 https://mirrors.aliyun.com/pypi/simple
  • 中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple
  • 清华大学 https://pypi.tuna.tsinghua.edu.cn/simple
  • 中国科学技术大学 http://pypi.mirrors.ustc.edu.cn/simple

  虽然 QML 中提供了多个样式可供使用,但是用户有时还是想实现自定义的外观。这里,我们新建一个 MyButton.qml 文件,用来存放自定义的组件。

import QtQuickRectangle {id: containerRectIdwidth: buttonTextId.implicitWidth + 60height: buttonTextId.implicitHeight + 20color: "#99CCFF"// 为内部的Text元素提供一个别名属性,方便在外部设置按钮的文本property alias buttonText: buttonTextId.textsignal buttonClicked()                                                      // 自定义一个信号border {width: 1color: "#666666"}Text {id: buttonTextIdanchors.centerIn: parenttext: "按钮"font.pointSize: 16color: "#FF6666"}MouseArea {id: mouseAreaIdanchors.fill: parentonClicked: {containerRectId.buttonClicked()                                     // 触发信号}}
}

  在 QML 中,我们无法使用自定义组件内部元素的属性,因此,我们需要使用 alias 关键字给内部元素的属性起一个别名,方便在外部设置该内部元素的属性值。

  我们新建一个 template.qml 文件,在该文件中调用自定义的 QML 组件。

import QtQuick.Window
import QtQuick.Layouts// Window控件表示一个顶级窗口
// 在QML中,元素是通过大括号{}内的属性来配置的。
Window {width: 800                                                                  // 窗口的宽度height: 600                                                                 // 窗口的高度visible: true                                                               // 显示窗口color: "lightgray"                                                          // 窗口的背景颜色Text {id: textIdanchors.centerIn: parentfont.pointSize: 32color: "#FF6666"}Column {MyButton {buttonText: "按钮1"onButtonClicked: {textId.text = "按钮1被点击了"}}MyButton {buttonText: "按钮2"onButtonClicked: {textId.text = "按钮2被点击了"}}}
}

  这里,我们将 template.qml 文件和 MyButton.qml 文件放置到同一级目录下。然后,我们可以在 template.qml 文件中直接用存放自定义组件的文件名创建自定义组件。

  自定义组件的名称一定要与存放自定义组件的文件名首字母一致,否则会报如下错误:

file:///E:/Software/Python/PySide6/Template/template.qml:13:9: MyButton is not a type
file:///E:/Software/Python/PySide6/Template/template.qml: File name case mismatch   

  自定义组件的存放文件的首字母一定要大写,否则会报如下错误:

file:///E:/Software/Python/PySide6/Template/template.qml:22:9: Cannot assign to non-existent property "myButton"

  我们新建一个 template.py 文件,用来加载 template.qml 文件。

import sysfrom PySide6.QtWidgets import QApplication
from PySide6.QtQml import QQmlApplicationEngineif __name__ == "__main__":app = QApplication(sys.argv)                                                # 1.创建一个QApplication类的实例engine = QQmlApplicationEngine()                                            # 2.创建QML引擎对象engine.load("template.qml")                                                 # 3.加载QML文件sys.exit(app.exec())                                                        # 4.进入程序的主循环并通过exit()函数确保主循环安全结束

这里自定义组件的 QML 文件名的首字母一定要大写。

自定义的组件名与 QML 文件名一致。

组件实例的 id 和组成组件的顶层 Itemid 是各自独立的。

二、使用component自定义组件

  我们修改 template.qml 文件的内容,使用 component 自定义一个组件。

import QtQuick.Window// Window控件表示一个顶级窗口
// 在QML中,元素是通过大括号{}内的属性来配置的。
Window {width: 800                                                                  // 窗口的宽度height: 600                                                                 // 窗口的高度visible: true                                                               // 显示窗口color: "lightgray"// MyButton为自定义的组件名component MyButton: Rectangle {id: containerRectIdwidth: buttonTextId.implicitWidth + 60height: buttonTextId.implicitHeight + 20color: "#99CCFF"// 为内部的Text元素提供一个别名属性,方便在外部设置按钮的文本property alias buttonText: buttonTextId.textsignal buttonClicked()                                                  // 自定义一个信号border {color: "#666666"width: 1}Text {id: buttonTextIdtext: "按钮"font.pointSize: 16color: "#FF6666"anchors.centerIn: parent}MouseArea {id: mouseAreaIdanchors.fill: parentonClicked: {containerRectId.buttonClicked()                                 // 触发信号}}}Text {id: textIdanchors.centerIn: parentfont.pointSize: 32color: "#FF6666"}Row {spacing: 20MyButton {buttonText: "按钮1"onButtonClicked: {textId.text = "按钮1被点击了"}}MyButton {buttonText: "按钮2"onButtonClicked: {textId.text = "按钮2被点击了"}}}
}

三、Component组件

  Component 是由 Qt 框架或开发者封装好的、只暴露了必要接口的 QML 类型,可以重复利用。一个 QML 组件就像一个黑盒子,它通过属性、信号、函数和外部世界交互。

  Component 有两个信号:completed() 信号会在 对象实例化后 发出的信号,destruction() 信号会在 在对象开始销毁 时发出x信号。

  修改 template.qml 文件的内容。

import QtQuick.Window// Window控件表示一个顶级窗口
// 在QML中,元素是通过大括号{}内的属性来配置的。
Window {width: 800                                                                  // 窗口的宽度height: 600                                                                 // 窗口的高度visible: true                                                               // 显示窗口color: "lightgray"// 对象实例化后发出的信号。一旦建立了完整的 QML 环境,它就可用于在启动时执行脚本代码。Component.onCompleted: {console.log("Component.onCompleted")console.log("width: " + width, ", height: " + height, ", color: " + color)}// 在对象开始销毁时发出信号Component.onDestruction: {console.log("Component.onDestruction")}
}

  我们还可以自定义一个 ComponentComponent 只能包含一个顶层 Item,而且在这个顶层 Item 之外不能定义除了 id 属性以外的任何数据。而在顶层 Item 之内,则可以包含更多的子元素来协同工作,最终形成一个具有特定功能的组件。

import QtQuick.Window// Window控件表示一个顶级窗口
// 在QML中,元素是通过大括号{}内的属性来配置的。
Window {width: 800                                                                  // 窗口的宽度height: 600                                                                 // 窗口的高度visible: true                                                               // 显示窗口color: "lightgray"// 自定义一个Componoent,需要手动加载才会显示Component {// Component不能定义除id以外的其它属性id: buttonComponent// Component只能有一个顶层ItemRectangle {id: containerRectIdwidth: buttonTextId.implicitWidth + 60height: buttonTextId.implicitHeight + 20color: "#99CCFF"// 为内部的Text元素提供一个别名属性,方便在外部设置按钮的文本property alias buttonText: buttonTextId.textsignal buttonClicked()                                              // 自定义一个信号border {width: 1color: "#666666"}Text {id: buttonTextIdanchors.centerIn: parenttext: "按钮"font.pointSize: 16color: "#FF6666"}MouseArea {id: mouseAreaIdanchors.fill: parentonClicked: {containerRectId.buttonClicked()                                     // 触发信号}}}}
}

四、使用Loader动态加载组件

  Loader 用来动态加载 QML 组件。我们可以把 Loader 作为占位符使用,在需要显示某个元素时,才使用 Loader 把它加载进来。

  我们可以使用 Loadersource 属性 加载一个 QML 文档,也可以通过其 sourceComponent 属性 加载一个 Component 对象。当 LoadersourcesourceComponent 属性发生变化时,它之前加载的 Component 会自动销毁,新对象会被加载。将 source 设置为一个 空字符串 或将 sourceComponent 设置为 undefined,将会 销毁当前加载的对象,相关的资源也会被释放,而 Loader 对象则变成一个空对象。

  Loaderitem 属性 指向它加载的组件的顶层 Item。对于 Loader 加载的 Item,它暴露出来的接口,如属性、信号等,都可以通过 Loaderitem 属性来访问。

  虽然 Loader 本身是 Item 的派生类,但没有加载 ComponentLoader 对象是不可见的,没什么实际的意义,只是个占位符号,而一旦你加载了一个 ComponentLoader 的大小、位置等属性却可以影响它所加载的 Component

  如果你没有显式指定 Loader 的大小,那么 Loader 会将自己的尺寸调整为与它加载的可见 Item 的尺寸一致。如果 Loader 的大小通过 widthheight或锚布局显式设置了,那么它加载的可见 Item 的尺寸会被调整以便适应 Loader 的大小。不管是哪种情况,Loader 和它所加载的 Item 具有相同的尺寸,这确保你使用锚来布局 Loader 就等同于布局它加载的 Item

  如果我们要加载的 Component 比较大,则可能比较卡顿。此时你可以设置 asynchronous 属性为 true开启异步加载模式,当 status(枚举值)的值为 Loader.Ready 时表示 已经加载完毕status 属性的取值如下:

Loader.Null
Loader.Ready 
Loader.Loading
Loader.Error

  如果 Loader 加载的 Item处理按键事件,那么必须将 Loader 对象的 focus 属性设置为 true。又因为 Loader 本身也是一个焦点敏感的对象,所以如果它加载的 Item 处理了按键事件,则应当将事件的 accepted 属性设置为 true,以免已经被吃掉的事件再传递给 Loader

  修改 template.qml 文件的内容。

import QtQuick.Window// Window控件表示一个顶级窗口
// 在QML中,元素是通过大括号{}内的属性来配置的。
Window {width: 800                                                                  // 窗口的宽度height: 600                                                                 // 窗口的高度visible: true                                                               // 显示窗口color: "lightgray"// 自定义一个Componoent,需要手动加载才会显示Component {// Component不能定义除id以外的其它属性id: buttonComponentId// Component只能有一个顶层ItemRectangle {id: containerRectIdwidth: buttonTextId.implicitWidth + 60height: buttonTextId.implicitHeight + 20color: "#99CCFF"// 为内部的Text元素提供一个别名属性,方便在外部设置按钮的文本property alias buttonText: buttonTextId.textsignal buttonClicked()                                              // 自定义一个信号border {width: 1color: "#666666"}Text {id: buttonTextIdanchors.centerIn: parenttext: "按钮"font.pointSize: 16color: "#FF6666"}MouseArea {id: mouseAreaIdanchors.fill: parentonClicked: {containerRectId.buttonClicked()                                     // 触发信号}}}}Text {id: textIdanchors.centerIn: parentfont.pointSize: 32color: "#FF6666"}Row {spacing: 20Loader {id: firstButtonIdsourceComponent: buttonComponentId                                  // 加载一个Component对象asynchronous: true                                                  // 异步加载// 加载完成后会触发loaded信号onLoaded: {var customButton = firstButtonId.item                           // 获取加载组件顶层的Item对象customButton.buttonText = "第一个按钮"customButton.buttonClicked.connect(function() {textId.text = "第一个按钮被点击了"})}}Loader {id: secondButtonIdsourceComponent: buttonComponentId                                  // 加载一个Component对象asynchronous: true                                                  // 异步加载// 加载完成后会触发loaded信号onLoaded: {var customButton = secondButtonId.item                          // 获取加载组件顶层的Item对象customButton.buttonText = "第二个按钮"customButton.buttonClicked.connect(function() {textId.text = "第二个按钮被点击了"})}}}
}
http://www.hskmm.com/?act=detail&tid=25126

相关文章:

  • python语法记录
  • 2025 年储罐厂家推荐最新公司权威排行榜榜单发布,深度解析衬四氟储罐 / 硫酸储罐 / 盐酸储罐工厂选购指南
  • UnicodeEncodeError: locale codec cant encode character \u5e74 in position 2: encoding error
  • 2025 年生物除臭设备厂家最新推荐排行榜:覆盖污水处理厂 / 垃圾中转站等多场景,助力企业精准挑选优质设备
  • 2025 年球墨铸铁管公司:重庆南恩物资全品类管材供应与市政工程适配解决方案解析
  • 2025生物除臭设备厂家最新品牌企业推荐排行榜揭晓:印染厂污水,食品厂污水,污水处理厂,污水泵站,污水站,餐厨垃圾,屠宰场,厨余垃圾生物除臭设备公司推荐
  • 2025 工业加热器选型必看:六大加热器实力厂家深度推荐,覆盖多场景加热设备解决方案
  • YOLO模型部署
  • 从理念到沙盘:用悟空博弈模拟器点亮人机共治的曙光
  • 深入解析:Redis事务详解:原理、使用与注意事项
  • phone num
  • Perplexity发布搜索API,驱动下一代AI应用开发
  • PWN手的成长之路-09-SWPUCTF 2023 秋季新生赛Shellcode
  • 20251005 总结
  • OKR1
  • 2025 年装盒机制造厂 TOP 企业品牌推荐排行榜,自动化 / 喷胶 / 牙膏 / 手机壳 / 3C 数码 / 内外盒 / 面膜 / 电子产品 / 玩具 / 日用品装盒机推荐这十家公司!
  • 英语_阅读_Chinas Spring Festival_待读
  • 2025 年自动包装生产线 TOP 企业品牌推荐排行榜!食品行业 / 日化产品 / 智能化 / 小型 / 多功能集成 / 柔性 / 后道 / 高速自动包装生产线推荐!
  • 题解:AT_arc181_e [ARC181E] Min and Max at the edge
  • 酵母单杂交实验:解密 “转录因子 - DNA 互作” 的核心工具
  • api调用钉钉群机器人发信息 - 规格严格
  • 2025 年氢氧化铝生产厂家 TOP 品牌榜单来袭,阻燃,高白,酸融,导热,超细,微粉级,低粘度,灌封胶用,覆铜板用氢氧化铝公司推荐!
  • 飞算 JavaAI 赋能老工程重构:破旧立新的高效利器
  • P14139 题解
  • AI 自我理解边界
  • 2025钢球厂家最新企业品牌推荐排行榜,轴承钢球,不锈钢球,碳钢球,精密钢球,440C不锈钢球推荐这十家公司!
  • 2025 年工业提升门厂家最新企业品牌推荐排行榜,汇峰节能科技彰显行业影响力!
  • 什么是偏微分方程?
  • 2025 权威推荐!电梯源头品牌 TOP5 排行榜:实力厂家精选,品质之选不容错过
  • 钉钉红包性能优化之路 - 实践