摘要:介绍 Text 的换行、省略和字体自适应能力,帮助文本在有限宽度、动态尺寸和大屏场景下保持良好阅读体验。
实际项目里,文本长度和容器尺寸往往是不确定的。列表项标题可能超长、卡片宽度会随窗口变化、大屏上的数字需要自动撑满空间。Text 提供了三组属性来应对这些问题:换行、省略和字体自适应。这篇把这三组属性的用法和注意点一次讲清楚。
三种场景一览
| 需求 | 关键属性 | 解决的问题 |
|---|---|---|
| 控制换行 | wrapMode | 长文本在有限宽度内如何折行 |
| 截断显示 | elide + maximumLineCount | 超出范围的文本用省略号收尾 |
| 自动缩放 | fontSizeMode + minimumPixelSize | 文字随容器大小自动调整字号 |
这三个能力经常组合使用,比如新闻列表的摘要需要 "两行省略",大屏 KPI 数字需要 "自适应容器"。
Text 文本换行
wrapMode 决定长文本如何折行。这个 demo 展示了 NoWrap、WordWrap、Wrap 三种模式的区别。
演示代码
import QtQuick
import QtQuick.Layouts
FadeInAnimation {
ColumnLayout {
anchors.fill: parent
anchors.margins: 20
spacing: 15
// ... 省略标题组件 TitleSeparator ...
ColumnLayout {
Layout.leftMargin: 20
spacing: 15
Text {
Layout.preferredWidth: 250
text: "NoWrap: This is a very long text that will not wrap by default"
wrapMode: Text.NoWrap
font.pointSize: 12
}
Text {
Layout.preferredWidth: 250
text: "WordWrap: This is a very long text that only wraps at word boundaries"
wrapMode: Text.WordWrap
font.pointSize: 12
}
Text {
Layout.preferredWidth: 250
text: "Wrap: This is a very long text that prefers word boundaries but can break anywhere if needed"
wrapMode: Text.Wrap
font.pointSize: 12
}
}
Item { Layout.fillHeight: true }
}
}
关键逻辑解析
Text.NoWrap:不换行,超出部分直接绘制出去Text.WordWrap:只在单词边界换行,阅读体验最好Text.Wrap:优先单词边界,必要时可在任意位置断行- 常用搭配:
wrapMode: Text.WordWrap+Layout.fillWidth: true
适用场景
WordWrap 适合文章正文、说明文字;Wrap 适合路径、URL、代码片段这类需要严格填满宽度的内容;NoWrap 适合配合 elide 做单行截断标题。
注意点
中文没有明显的单词边界,WordWrap 和 Wrap 在中文下的表现差异不大。但在英文界面里,两者区别很明显,不要乱用。
Text 文本省略
列表、卡片里经常需要把过长的文字截断显示。这个 demo 展示了右侧省略、左侧省略、中间省略,以及多行省略的写法。
演示代码
import QtQuick
import QtQuick.Layouts
FadeInAnimation {
ColumnLayout {
anchors.fill: parent
anchors.margins: 20
spacing: 15
// ... 省略标题组件 TitleSeparator ...
ColumnLayout {
Layout.leftMargin: 20
spacing: 12
Text {
Layout.preferredWidth: 250
text: "ElideRight: 这是一段需要被省略的长文本"
elide: Text.ElideRight
font.pointSize: 11
}
Text {
Layout.preferredWidth: 250
text: "ElideLeft: 这是一段需要被省略的长文本"
elide: Text.ElideLeft
font.pointSize: 11
}
Text {
Layout.preferredWidth: 250
text: "ElideMiddle: 这是一段需要被省略的长文本"
elide: Text.ElideMiddle
font.pointSize: 11
}
Text {
Layout.preferredWidth: 250
text: "多行省略: 这是一段很长的文本,用来演示 maximumLineCount 属性的效果。当文本超过指定行数时,会被省略。"
maximumLineCount: 2
elide: Text.ElideRight
wrapMode: Text.WordWrap
font.pointSize: 10
}
}
Item { Layout.fillHeight: true }
}
}
关键逻辑解析
elide:省略模式,ElideRight/ElideLeft/ElideMiddlemaximumLineCount:最多显示几行,配合wrapMode使用- 多行省略必须同时设置
wrapMode: Text.WordWrap和elide: Text.ElideRight
适用场景
ElideRight 适合大多数列表标题;ElideMiddle 适合文件路径,保留开头和结尾;ElideLeft 适合显示日志时间戳后面的关键信息。多行省略适合新闻摘要、商品简介等场景。
注意点
单行省略只需要设置 elide 和固定宽度;多行省略必须同时开启 wrapMode,否则 maximumLineCount 不会生效。另外,elide 对富文本(RichText)的支持有限,复杂场景建议用 TextMetrics 自己截断。
Text 字体自适应
做响应式布局或大屏展示时,希望文字自动填满容器。fontSizeMode 就是干这个的。这个 demo 展示了 HorizontalFit、VerticalFit、Fit 三种模式,最后一个容器还可以拖动改变大小来观察效果。
演示代码
import QtQuick
import QtQuick.Layouts
FadeInAnimation {
ColumnLayout {
anchors.fill: parent
anchors.margins: 20
spacing: 15
// ... 省略标题组件 TitleSeparator ...
ColumnLayout {
Layout.fillWidth: true
Layout.leftMargin: 20
Layout.rightMargin: 20
spacing: 15
Rectangle {
Layout.preferredWidth: 300
Layout.preferredHeight: 40
color: "#fff3e0"
border.color: "#ffb74d"
radius: 4
Text {
anchors.fill: parent
anchors.margins: 4
text: "HorizontalFit 适配宽度"
fontSizeMode: Text.HorizontalFit
font.pixelSize: 72
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
Rectangle {
Layout.preferredWidth: 300
Layout.preferredHeight: 50
color: "#e3f2fd"
border.color: "#42a5f5"
radius: 4
Text {
anchors.fill: parent
anchors.margins: 4
text: "VerticalFit 适配高度"
fontSizeMode: Text.VerticalFit
font.pixelSize: 72
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
Rectangle {
Layout.preferredWidth: 300
Layout.preferredHeight: 60
color: "#e8f5e9"
border.color: "#66bb6a"
radius: 4
Text {
anchors.fill: parent
anchors.margins: 4
text: "Fit 适配宽高"
fontSizeMode: Text.Fit
minimumPixelSize: 10
font.pixelSize: 72
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
Rectangle {
id: resizableBox
Layout.preferredWidth: 300
Layout.preferredHeight: 60
color: "#f3e5f5"
border.color: "#ab47bc"
border.width: 2
radius: 4
Text {
anchors.fill: parent
anchors.margins: 4
text: "拖动改变大小"
fontSizeMode: Text.Fit
minimumPixelSize: 10
font.pixelSize: 72
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
MouseArea {
anchors.right: parent.right
anchors.bottom: parent.bottom
width: 24
height: 24
cursorShape: Qt.SizeFDiagCursor
preventStealing: true
property real startX
property real startY
onPressed: (mouse) => {
startX = mouse.x
startY = mouse.y
}
onPositionChanged: (mouse) => {
var newW = resizableBox.width + (mouse.x - startX)
var newH = resizableBox.height + (mouse.y - startY)
if (newW > 80) resizableBox.width = newW
if (newH > 30) resizableBox.height = newH
startX = mouse.x
startY = mouse.y
}
}
}
}
Item { Layout.fillHeight: true }
}
}
关键逻辑解析
fontSizeMode: Text.HorizontalFit:宽度变化时字体跟着变,高度固定fontSizeMode: Text.VerticalFit:高度变化时字体跟着变,宽度固定fontSizeMode: Text.Fit:同时适配宽高minimumPixelSize:限制最小字号,避免容器太小时字缩到看不见font.pixelSize设一个较大值作为上限,实际大小由容器决定
适用场景
Text.Fit 最适合大屏数字展示、欢迎页标题、广告牌文字。HorizontalFit 适合宽度会变化但高度固定的标签栏。VerticalFit 适合竖向布局里的标题。
注意点
fontSizeMode 只在文字内容较短时效果最好。如果文字很长,字号会缩到很小才能塞进容器,这时应该改用 wrapMode 或 elide。另外,自适应模式下建议始终设置 minimumPixelSize,避免极端情况下文字不可读。
对比表格
| 需求 | 关键属性 | 注意点 |
|---|---|---|
| 控制换行 | wrapMode | 多行用 WordWrap |
| 截断显示 | elide | 单行省略只需 elide,多行需加 maximumLineCount + wrapMode |
| 自动缩放 | fontSizeMode | 配合 minimumPixelSize 使用 |
运行验证
- Qt Creator 打开
qml_text/CMakeLists.txt - 按
Ctrl+R运行 - 在左侧导航切换文本换行、文本省略、字体自适应
扩展复用方向
- 封装
EllipsisText组件,默认开启ElideRight,支持设置最大行数 - 在大屏 KPI 展示中用
Text.Fit让数字自动撑满卡片 - 新闻列表用
maximumLineCount: 2+elide: ElideRight做两行摘要 - 做响应式卡片时,结合
Layout.fillWidth和WordWrap让正文随窗口自动换行
小结
换行、省略、自适应是 Text 处理动态内容的三把利器。wrapMode 解决文本折行,elide 解决超长截断,fontSizeMode 解决字号适配。三者可以单独使用,也可以组合:比如一个响应式新闻卡片,标题用 elide 单行省略,摘要用 wrapMode + maximumLineCount 多行省略,核心数据用 fontSizeMode 自动撑满。掌握这些属性,就能让文本在不同尺寸下都保持良好的阅读体验。
已验证环境:
- Qt 版本:Qt 6.11.1
- 操作系统:Windows 11
- GitHub:QML-Minimal-Demos/qml_text