QML Text属性width、implicitWidth、contentWidth更新时序
创始人
2025-05-29 07:21:46
0

为了实现一种较复杂的Row, 该Row在整个屏幕是居中的, Row里面有2个Text A、B和一个分隔符(图片). B的长度取决于A的长度以及三个部件的总长度. 总长度是720而Text A优先显示, 则B可显示长度为720-A长度-分隔符,Text B显示不下则显示“...”. 大概效果是(第一行):

Text B显示得下效果是:

为了实现出上述需求, QML代码如下:

    Row {anchors.horizontalCenter: parent.horizontalCenterspacing: Skin.MARGIN_8SLText {id: subLabelwidth: Math.min(implicitWidth, Skin.CALL_INFO_WIDTH)visible: text != ""}SLSeparatorDot {anchors.verticalCenter: parent.verticalCentervisible: subLabel.visible && hgLabel.visible}SLText {id: hgLabelwidth: getHgWidth(subLabel.implicitWidth, hgLabel.implicitWidth)elide: Text.ElideRightonImplicitWidthChanged: {console.log("!!!hgLabel onImplicitWidthChanged:"+implicitWidth);}onContentWidthChanged: {console.log("!!!hgLabel onContentWidthChanged:"+contentWidth);}onWidthChanged: {console.log("!!!hgLabel onWidthChanged:"+width);}function getHgWidth(subImplicitWidth, hgImplicitWidth) {var hgWidth = 0;console.log("!!!getHgWidth0 subImplicitWidth:"+subImplicitWidth+",hgImplicitWidth:"+hgImplicitWidth);if (hgImplicitWidth > 0 && subImplicitWidth > 0) {hgWidth = Math.min(hgImplicitWidth, Skin.CALL_INFO_WIDTH - subImplicitWidth - Skin.SEPARATOR_DOT_WIDTH - Skin.MARGIN_8 * 2)}else if (hgImplicitWidth > 0) {hgWidth = Math.min(hgImplicitWidth, Skin.CALL_INFO_WIDTH)}return hgWidth;}}}SLText {id: demoanchors.horizontalCenter: parent.horizontalCentertext: "xxxxxxxx"onImplicitWidthChanged: {console.log("!!!demo onImplicitWidthChanged:"+implicitWidth);}onContentWidthChanged: {console.log("!!!demo onContentWidthChanged:"+contentWidth);}onWidthChanged: {console.log("!!!demo onWidthChanged:"+width);}}

由于项目中的Text内容是动态加载的,时序和固定内容的Text有些许区别. 我特意加了一个普通Text作为对比,并在每个要关注的signal的响应的slot(onXxxChanged)中打出log去观察时序:

8104 DEB Mar 16 16:00:53.586844 (25414-25414) guiapp-!!!demo onWidthChanged:101.5
8105 DEB Mar 16 16:00:53.586912 (25414-25414) guiapp-!!!demo onImplicitWidthChanged:101.5
8106 DEB Mar 16 16:00:53.586966 (25414-25414) guiapp-!!!demo onContentWidthChanged:101.5
8107 DEB Mar 16 16:00:53.587004 (25414-25414) guiapp-!!!demo onImplicitWidthChanged:101.58103 DEB Mar 16 16:00:53.585190 (25414-25414) guiapp-!!!getHgWidth0 subImplicitWidth:0,hgImplicitWidth:0
8128 DEB Mar 16 16:00:53.637086 (25414-25414) guiapp-!!!getHgWidth0 subImplicitWidth:172.6875,hgImplicitWidth:0
8129 DEB Mar 16 16:00:53.637427 (25414-25414) guiapp-!!!hgLabel onImplicitWidthChanged:201.203125
8130 DEB Mar 16 16:00:53.637477 (25414-25414) guiapp-!!!getHgWidth0 subImplicitWidth:172.6875,hgImplicitWidth:201.203125
8131 DEB Mar 16 16:00:53.637527 (25414-25414) guiapp-!!!hgLabel onWidthChanged:201.203125
8132 DEB Mar 16 16:00:53.637640 (25414-25414) guiapp-!!!hgLabel onContentWidthChanged:201.203125

可以看到,

对于动态内容Text, width被getHgWidth绑定, 故function一定先调用, 不论implicitWidth和contentWidth是否为0. 一旦有text动态更新,先变化的属性是implicitWidth, 这将trigger function再次调用,这将导致width更新, 而最后更新的是contentWidth.

对于固定内容Text, witdh未设置, 从log来看width先变化, 然后是implicitWidth最后是contentWidth. 一些资料对于Text的实际文字长度选用contentWidth可能是有问题的. 在此我们得知,如果要尽早得知Text的实际文字长度的更新应该使用implicitWidth.

说句题外话,我之前getHgWidth想用Text A和Text B的visible属性来作为function参数来更新witdh,但发现虽然每次visible更新但是implicitWidth/contentWidth可能为0(我一旦在onVisible里面打log去print implicitWidth/contentWidth则函数体内implicitWidth/contentWidth就被更新了). 可见QML内部这些属性的更新有自己的时序, 而且getHgWidth函数体内即便有implicitWidth和contentWidth但拿到的值并不是最新的. 因此尝试使用implicitWidth/contentWidth作为参数去 trigger function, 结果是达到预期的. 因此推断QML中function是由参数而非函数体内变量去trigger的.

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...