QT QML 中实现高亮功能

最近修改QT项目,需要实现一个搜索高亮的功能,实现方式是匹配到关键字,通过span上写样式然后包裹关键字

qml 复制代码
<span style="background-color:#fef08a">keyword</span>

实现效果如下

一、页面结构

页面主要由搜索框和结果列表组成。

yaml 复制代码
ColumnLayout {
    anchors.fill: parent
    anchors.margins: 20
    spacing: 12

    TextField {
        id: searchField
        Layout.fillWidth: true
        placeholderText: "请输入关键字"
    }

    ListView {
        id: resultList
        Layout.fillWidth: true
        Layout.fillHeight: true
        model: filteredItems

        delegate: Text {
            width: resultList.width
            text: highlighted(modelData.content)
            textFormat: Text.RichText
            wrapMode: Text.Wrap
        }
    }
}

因为高亮内容使用了 span 标签,所以 Text 需要设置富文本:

vbnet 复制代码
textFormat: Text.RichText

否则页面会直接显示 HTML 标签,无法渲染高亮样式。

准备测试数据:

css 复制代码
property var sourceItems: [
    { content: "QML 是一种声明式界面开发语言" },
    { content: "使用 QML 可以快速开发 Qt 界面" },
    { content: "Text.RichText 支持简单的 HTML 标签" }
]

property var filteredItems: [] // 筛选列表 
readonly property string keyword: searchField.text // 搜索关键字

页面加载完成后显示全部数据:

scss 复制代码
// 搜索方法
Component.onCompleted: updateResults() 

二、搜索监听

监听搜索框的 textChanged 信号:

yaml 复制代码
TextField {
    id: searchField
    Layout.fillWidth: true
    placeholderText: "请输入关键字"

    onTextChanged: updateResults()
}

搜索方法如下:

scss 复制代码
function updateResults() {
    const target = searchField.text.toLocaleLowerCase()

    if (!target.length) {
        filteredItems = sourceItems.slice(0)
        return
    }

    filteredItems = sourceItems.filter(function(item) {
        const content = String(item.content || "").toLocaleLowerCase()
        return content.indexOf(target) !== -1
    })
}

搜索内容和原始内容统一转换成小写,因此匹配时不区分大小写。

当搜索框为空时:

ini 复制代码
filteredItems = sourceItems.slice(0)

列表会重新显示全部数据。

三、高亮实现

首先对原始文本中的 HTML 特殊字符进行转义:

javascript 复制代码
function escapeHtml(value) {
    return String(value === undefined || value === null ? "" : value)
            .replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;")
}

然后实现关键字高亮:

vbnet 复制代码
function highlighted(value) {
    const text = String(value === undefined || value === null ? "" : value)

    if (!keyword.length)
        return escapeHtml(text)

    const source = text.toLocaleLowerCase()
    const target = keyword.toLocaleLowerCase()

    let result = ""
    let start = 0
    let index = source.indexOf(target)

    while (index !== -1) {
        result += escapeHtml(text.slice(start, index))

        result += "<span style='background-color:#fef08a'>"
                + escapeHtml(text.slice(index, index + keyword.length))
                + "</span>"

        start = index + keyword.length
        index = source.indexOf(target, start)
    }

    return result + escapeHtml(text.slice(start))
}

高亮实现的核心代码是:

less 复制代码
result += "<span style='background-color:#fef08a'>"
        + escapeHtml(text.slice(index, index + keyword.length))
        + "</span>"

indexOf() 用于获取关键字位置,slice() 截取匹配到的原始文字,再通过带背景颜色的 span 标签进行包裹。

while 循环会继续查找下一处匹配,因此一段文字中出现多个相同关键字时,可以全部高亮显示。

相关推荐
mengzhi啊几秒前
把数据存入sql数据库。qt,c++。
数据库·sql·qt
mengzhi啊6 小时前
SerialPortItem对串口再封装一层,省去一些常用的步骤,不用每次都去写类
qt
用户83344239661418 小时前
从批量操作到任务中心,再到现场工作台:DeviceForge v2.10—v2.12 完整演进
qt
宛 禾20 小时前
Qt 控件入门:QLabel 从拖拽到对象树,一篇讲透
c++·qt·学习
打工仔折腾 AI1 天前
Qt网络编程实战:UDP、TCP到HTTP的落地经验与选型
网络·人工智能·后端·python·qt·udp·ai agent 实战
Lhan.zzZ1 天前
Linux + Qt/QML:解决 QtQuick.VirtualKeyboard.Plugins 模块加载失败与环境变量配置
linux·数据库·qt
誰能久伴不乏1 天前
QT工业上位机一次「指令静默丢失」的排查
qt·docker·github
扶尔魔ocy2 天前
【qt openGL入门笔记】OSG实现飞机模型在网格图上飞行并进行态势标绘(四)
qt·opengl·osg
橙橙笔记2 天前
QT安卓软件的制作
android·git·qt·软件
芦芭荞2 天前
QT使用xml模版生成word文档
xml·qt·word