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.mzph.cn/news/928717.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CF1611E2 Escape The Maze (hard version)

CF1611E2 Escape The Maze (hard version)题目简化 我在1号节点,你有k个朋友,分别在a1,a2,a3....ak的位置,在同一时间内可以移动1步,我不能和朋友走到同一个节点,如果我能走到叶节点,我就赢了,输出-1,否则必然…

P8186 [USACO22FEB] Redistributing Gifts S

P8186 [USACO22FEB] Redistributing Gifts S题目 每一个牛都有一个自己喜欢的排列,并且初始的时候,每只牛都是i,求经过n次交换后,每只牛能拿到的最喜欢的 我们来简化这n次操作,a1->a2,a2->a3,a3->a4,a4-…

重庆网站制品牌建设推荐

MySQL强制索引和禁止某个索引1、mysql强制使用索引:force index(索引名或者主键PRI)例如:select * from table force index(PRI) limit 2;(强制使用主键)select * from table force index(ziduan1_index) limit 2;(强制使用索引"ziduan1_index")select * from table …

做视频解析网站是犯法的么网站备案时间就是正式上线时间吗

题目描述 给出一个初始序列fA1;A2;:::Ang,要求你编写程序支持如下操作: 1. ADDxyD:给子序列fAx:::Ayg的每个元素都加上D。例如对f1,2, 3,4,5g执行"ADD 241" 会得到f1,3,4,5,5g。 2. REVERSExy:将子序列fAx:::Ayg翻转。例…

python语法记录

map()函数 A=[1,-3,5] A_abs = list(map(abs, A))map(func, A),把func函数作用到A的每个元素上,返回的是惰性迭代器,依次产出1,3,5,不能直接打印或索引; 用list()把它一次性拉出来,变成普通列表[1, 3, 5]。

怎么免费建立网站做推广天津雍鑫建设投资集团网站

问题描述 在Mac上安装git,双击pkg进行安装,报如下图错误: 解决办法 不要双击pkg文件,改成选中文件之后,鼠标右键,选择“打开方式->安装器(默认)”,即可继续安装。 转载…

详细介绍:Go 语言 + Word 文档模板:WordZero 引擎如何让企业文档处理效率提升 300%?

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Go 即时通讯体系:客户端与服务端 WebSocket 通信交互

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

网站开发持续更新wordpress广告设置

大数据开发(Hadoop面试真题) 1、Hive count(distinct)有几个reduce,海量数据会有什么问题?2、既然HBase底层数据是存储在HDFS上,为什么不直接使用HDFS,而还要用HBase?3、Spark map join的实现原理&#xf…

2025 年储罐厂家推荐最新公司权威排行榜榜单发布,深度解析衬四氟储罐 / 硫酸储罐 / 盐酸储罐工厂选购指南

引言在当今工业领域,储罐作为储存各类液体、气体等物质的关键设备,其重要性不言而喻。从化工行业储存具有强腐蚀性的原料,到食品行业对卫生安全要求极高的产品储存,再到环保领域对污水、废气处理过程中的暂存需求等…

读混元image论文

读混元image论文https://www.yiyibooks.cn/arxiv/2509.23951v1/index.html

实用指南:跳动的爱心

实用指南:跳动的爱心2025-10-05 20:24 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-…

UnicodeEncodeError: locale codec cant encode character \u5e74 in position 2: encoding error

s= datetime.now().strftime(u"%Y年%m月%d日 %H:%M:%S" )UnicodeEncodeError: locale codec cant encode character \u5e74 in position 2: encoding error可行方案: import localefrom datetime import da…

2025 年生物除臭设备厂家最新推荐排行榜:覆盖污水处理厂 / 垃圾中转站等多场景,助力企业精准挑选优质设备

当前,恶臭污染在工业生产与城市生活中愈发凸显,污水处理厂、垃圾中转站、餐厨垃圾处理场等场所产生的恶臭气体,不仅影响周边居民生活,还危害人体健康,且随着环保标准不断提高,企业对高效环保除臭设备的需求极为迫…

杭州网站设计成功柚v米科技wordpress加载图片的速度

文章目录1. 题目2. 解题1. 题目 亚历克斯和李继续他们的石子游戏。许多堆石子 排成一行,每堆都有正整数颗石子 piles[i]。游戏以谁手中的石子最多来决出胜负。 亚历克斯和李轮流进行,亚历克斯先开始。最初,M 1。 在每个玩家的回合中&…

YOLO模型部署

一、环境搭建 第一步 显卡驱动查看 WIN+R键 进入命令终端 输入 nvidia-smi如果没有CUDA和CUDNN请自行安装,这里不再赘述 第二步 安装Anaconda 网站直接进行下载,这里不再进行安装教程 https://www.anaconda.com/down…

咸阳营销型网站开发北京制作网站主页

发布在linux上的机器,一般我们需要监测各项数据来证实服务器是没问题的, 如果出现问题,我们也可以通过以下指标找到问题的方向 容器指标硬件指标磁盘指标系统指标网络指标 容器指标 线程数 -当前容器内线程总数(平均到每个核的线程数)进程数 -当前容器…

从理念到沙盘:用悟空博弈模拟器点亮人机共治的曙光

从理念到沙盘:用"悟空博弈模拟器"点亮人机共治的曙光 当"AI元人文"的宏大构想遇上现实的算力壁垒,我们不必等待遥远的硬件革命。一条更智慧的道路已经显现:将其中最精妙的"悟空博弈"…

深入解析:Redis事务详解:原理、使用与注意事项

深入解析:Redis事务详解:原理、使用与注意事项pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", …