QML Text 点击交互与富文本

0 阅读6分钟

摘要:演示 Text 的可点击交互、超链接、HTML 富文本和 Markdown 支持,让轻量文本组件也能承担按钮和说明页职责。

文本在界面里不只是用来读,还可以点击、跳转、甚至承载格式化内容。这篇讲 Text 的四个进阶用法:可点击文本、链接交互、HTML 富文本和 Markdown 文本。它们能让你的界面少套一层 ButtonWebView

四种交互/富文本方案

需求方案复杂度
文本点击反馈Text + MouseArea
点击打开外链textFormat: Text.RichText + onLinkActivated
简单 HTML 富文本textFormat: Text.RichText
轻量 MarkdowntextFormat: Text.MarkdownText

这四种方案都基于 Text 本身,不需要额外引入 WebView,启动速度和内存占用都比嵌套浏览器小很多。

Text 可点击文本

Text 本身不处理鼠标事件,需要套一个 MouseArea。这个 demo 展示了点击切换颜色、按下缩放、按钮样式、边框按钮四种常见交互效果。

text-clickable.gif

演示代码

import QtQuick
import QtQuick.Layouts

FadeInAnimation {
    ColumnLayout {
        anchors.fill: parent
        anchors.margins: 20
        spacing: 15

        // ... 省略标题组件 TitleSeparator ...

        ColumnLayout {
            Layout.leftMargin: 20
            spacing: 12

            Text {
                id: clickText1
                text: "点击我切换颜色"
                font.pointSize: 13
                color: toggled ? "#E91E63" : "#1976D2"
                property bool toggled: false

                MouseArea {
                    anchors.fill: parent
                    onClicked: clickText1.toggled = !clickText1.toggled
                }
            }

            Text {
                id: clickText2
                text: "按下缩放效果"
                font.pointSize: 13
                color: pressed ? "#E91E63" : "#333"
                property bool pressed: false

                MouseArea {
                    anchors.fill: parent
                    onPressed: {
                        clickText2.pressed = true
                        clickText2.scale = 0.9
                    }
                    onReleased: {
                        clickText2.pressed = false
                        clickText2.scale = 1.0
                    }
                }

                Behavior on scale {
                    NumberAnimation { duration: 100 }
                }
            }

            Rectangle {
                width: 120
                height: 36
                radius: 4
                color: buttonArea.pressed ? "#1565C0" : "#1976D2"

                Text {
                    anchors.centerIn: parent
                    text: "按钮样式"
                    color: "white"
                    font.pointSize: 12
                }

                MouseArea {
                    id: buttonArea
                    anchors.fill: parent
                }

                Behavior on color {
                    ColorAnimation { duration: 100 }
                }
            }

            Rectangle {
                id: borderBtn
                width: 120
                height: 32
                radius: 16
                border.color: borderArea.pressed ? "#E91E63" : "#1976D2"
                border.width: 2
                color: borderArea.pressed ? "#fce4ec" : "white"

                Text {
                    anchors.centerIn: parent
                    text: "边框按钮"
                    color: borderBtn.border.color
                    font.pointSize: 12
                }

                MouseArea {
                    id: borderArea
                    anchors.fill: parent
                }
            }
        }

        Item { Layout.fillHeight: true }
    }
}

关键逻辑解析

  • MouseArea 必须 anchors.fill: parent 才能覆盖整个文本区域
  • 用自定义布尔属性记录状态,再用它驱动 colorscale
  • Behavior on scale / Behavior on color 让变化有过渡动画
  • 做按钮样式时,通常用 RectangleText,再套 MouseArea

适用场景

可点击文本适合做筛选标签、展开/收起按钮、文字型操作入口。相比 Button,它更轻量,样式完全由你控制,适合做扁平化设计的界面。

注意点

MouseArea 会拦截事件,如果文本放在 ScrollViewListView 里,要注意手势冲突。另外,可点击文本最好给用户一些视觉反馈,比如颜色变化或缩放,否则用户不知道能点。

Text 链接交互

textFormat: Text.RichText 支持 HTML 标签,点击链接时触发 linkActivated。这个 demo 展示了两个可点击的外部链接。

text-link.png

演示代码

import QtQuick
import QtQuick.Layouts

FadeInAnimation {
    ColumnLayout {
        anchors.fill: parent
        anchors.margins: 20
        spacing: 15

        // ... 省略标题组件 TitleSeparator ...

        ColumnLayout {
            Layout.leftMargin: 20
            spacing: 12

            Text {
                text: '点击访问 <a href="https://qt.io">Qt 官网</a>'
                textFormat: Text.RichText
                font.pointSize: 12
                linkColor: "#1976D2"
                onLinkActivated: (link) => {
                    Qt.openUrlExternally(link)
                }
            }

            Text {
                text: '点击打开 <a href="https://doc.qt.io/qt-6/qml-qtquick-text.html">Text 文档</a>'
                textFormat: Text.RichText
                font.pointSize: 12
                linkColor: "#1976D2"
                onLinkActivated: (link) => {
                    Qt.openUrlExternally(link)
                }
            }
        }

        Item { Layout.fillHeight: true }
    }
}

关键逻辑解析

  • textFormat: Text.RichTextText 按 HTML 解析
  • linkColor 控制超链接颜色
  • onLinkActivated 接收点击的 URL,再用 Qt.openUrlExternally 打开浏览器

适用场景

链接交互适合用户协议、隐私政策、帮助文档、关于页面里的外部链接。不需要单独放 Button,一段文字里就能嵌入可点击的链接。

注意点

onLinkActivated 收到的是字符串 URL,不要直接执行。建议做白名单校验或限制为 https:// 开头,避免恶意链接。另外,Qt.openUrlExternally 在部分平台可能需要额外权限。

Text 富文本(HTML)

Text.RichText 支持常用 HTML 标签,适合显示带格式的静态内容。这个 demo 展示了粗体、斜体、下划线、删除线、颜色、字号、标题和段落。

text-rich.png

演示代码

import QtQuick
import QtQuick.Layouts

FadeInAnimation {
    ColumnLayout {
        anchors.fill: parent
        anchors.margins: 20
        spacing: 15

        // ... 省略标题组件 TitleSeparator ...

        Text {
            text: "<b>粗体</b> <i>斜体</i> <u>下划线</u> <s>删除线</s>"
            textFormat: Text.RichText
            font.pointSize: 12
        }

        Text {
            text: "<font color='red'>红色</font> <font color='green'>绿色</font> <font color='blue'>蓝色</font>"
            textFormat: Text.RichText
            font.pointSize: 12
        }

        Text {
            text: "<font size='5'>大号</font> <font size='2'>小号</font>"
            textFormat: Text.RichText
            font.pointSize: 12
        }

        Text {
            text: "<h4>标题</h4><p>段落文本</p>"
            textFormat: Text.RichText
            font.pointSize: 10
        }

        // ... 省略说明文本 ...

        Item { Layout.fillHeight: true }
    }
}

关键逻辑解析

常用标签包括 biusfonth1-h6pbraimg。不需要引入 WebView,比 TextEdit 轻量很多。

适用场景

HTML 富文本适合提示说明、格式化内容、简单的图文混排。比如一个弹窗里的操作提示,用 <b> 标出重点,比放多个 Text 组件更紧凑。

注意点

Text.RichText 支持的 HTML 子集有限,复杂布局不要用。如果需要 CSS、表格、脚本,应该改用 WebEngineView。另外,图片标签 img 只支持本地路径或资源路径,加载网络图片需要额外处理。

Text Markdown 文本

Qt 6 的 Text 支持 Markdown,适合显示简单的格式化说明。这个 demo 展示了粗体、斜体、删除线、无序列表和有序列表。

text-md.png

演示代码

import QtQuick
import QtQuick.Layouts

FadeInAnimation {
    ColumnLayout {
        anchors.fill: parent
        anchors.margins: 20
        spacing: 15

        // ... 省略标题组件 TitleSeparator ...

        ColumnLayout {
            Layout.leftMargin: 20
            spacing: 12

            Text {
                text: "**粗体** *斜体* ~~删除线~~"
                textFormat: Text.MarkdownText
                font.pointSize: 12
            }

            Text {
                width: 200
                text: "- 列表项1\n- 列表项2\n- 列表项3"
                textFormat: Text.MarkdownText
                font.pointSize: 11
                wrapMode: Text.WordWrap
            }

            Text {
                width: 200
                text: "1. 有序项1\n2. 有序项2\n3. 有序项3"
                textFormat: Text.MarkdownText
                font.pointSize: 11
                wrapMode: Text.WordWrap
            }
        }

        // ... 省略说明文本 ...

        Item { Layout.fillHeight: true }
    }
}

关键逻辑解析

  • textFormat: Text.MarkdownText 启用 Markdown 解析
  • 支持 CommonMark 和 GitHub 扩展
  • 多行内容用 \n 分隔,配合 wrapMode 使用

适用场景

Markdown 适合更新日志、版本说明、用户反馈内容、从服务端拉取的富文本。因为 Markdown 源码比 HTML 更简洁,后端同学也更容易维护。

注意点

Qt 的 Markdown 解析器支持范围有限,表格、任务列表等高级特性可能渲染不出来。上线前要把目标语法在 demo 里跑一遍确认效果。另外,多行 Markdown 文本一定要记得设置 wrapMode,否则长列表会溢出容器。

对比表格

需求方案适用场景
文本可点击Text + MouseArea自定义按钮、标签筛选
点击打开外链textFormat: Text.RichText + onLinkActivated用户协议、帮助文档
简单富文本Text.RichText提示说明、格式化内容
轻量 MarkdownText.MarkdownText更新日志、简介

运行验证

  1. Qt Creator 打开 qml_text/CMakeLists.txt
  2. Ctrl+R 运行
  3. 在左侧导航切换可点击文本、链接交互、富文本 HTML、Markdown

扩展复用方向

  • 把可点击文本封装成 ClickableText 组件,支持 normal / hover / pressed 三种状态色
  • Text.RichText 做带图文的帮助页
  • Text.MarkdownText 显示从服务器拉取的 Markdown 说明
  • 给链接文本增加复制到剪贴板的功能,除了打开浏览器还能复制 URL

小结

Text 组件在交互和富文本方面的能力经常被低估。配合 MouseArea 可以做轻量按钮,配合 RichText 可以做链接和简单 HTML,配合 MarkdownText 可以展示后端维护的说明内容。这些方案的共同优势是轻量、启动快、不依赖 WebView。只要需求不复杂,优先考虑用 Text 解决,而不是直接引入更重的组件。


已验证环境