QML 滚动视图:ScrollView、Flickable,以及 ScrollIndicator 用法

QML 里最常用的滚动方式有:用ScrollView组件直接包起来、在Flickable组件中加上ScrollBar。如果只想显示提示不让人拖动就用ScrollIndicator。

这篇文章用三个 demo 把基础用法过一遍,看完就知道该选哪个。

ScrollView 滚动

一个简单的滚动示例:

演示代码

qml 复制代码
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts

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

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

        ScrollView {
            Layout.fillWidth: true
            Layout.fillHeight: true
            ScrollBar.vertical.policy: ScrollBar.AsNeeded
            ScrollBar.vertical.interactive: true

            ColumnLayout {
                anchors.fill: parent
                anchors.margins: 10

                Repeater {
                    model: 20
                    delegate: ItemDelegate {
                        background: Rectangle {
                            implicitWidth: 150
                            implicitHeight: 25
                            color: "#3498db"
                            radius: 4
                        }
                        contentItem: Text {
                            text: "This is Scroll Item " + index
                            color: "#fff"
                        }
                    }
                }
            }
        }
    }
}

直接使用 ScrollView 比较省事,用户只需要把内容丢进去,滚动条自动就有了。policy: AsNeeded 表示内容装不下时才显示滚动条,放得下就自动藏起来;interactive: true 表示滑块能用鼠标直接拖动。

这个演示demo里使用 Repeater 一次性生成了 20 条条目,把内容撑出可视高度,自然就能上下滚动。适用场景:设置页、长表单、条目数不定的纵向列表。

Flickable 双向滚动

当内容横竖都超出视图时,垂直、水平两条滚动条同时出现。

演示代码

qml 复制代码
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts

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

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

        Flickable {
            id: flickable
            Layout.fillWidth: true
            Layout.fillHeight: true
            clip: true  // 防止内容超出边界

            contentWidth: contentRect.width
            contentHeight: contentRect.height

            ScrollBar.vertical: ScrollBar { policy: ScrollBar.AlwaysOn }
            ScrollBar.horizontal: ScrollBar { policy: ScrollBar.AlwaysOn }

            Rectangle {
                id: contentRect
                width: 500
                height: 500
                color: "#3498db"
                Text {
                    text: "Scrollable Content"
                    anchors.centerIn: parent
                    font.pointSize: 20
                    color: "#fff"
                }
            }
        }
    }
}

Flickable 本身只负责让内容能动起来,滚动条需要自己加上,默认不显示。ScrollBar.vertical 和 ScrollBar.horizontal 这两个附加属性,就是分别对应垂直、水平方向的滚动条。

想让内容滚得动,contentWidth 和 contentHeight 必须设成内容的真实宽高------视口比内容小,才有东西可以滚;clip: true 再把超出框的内容裁掉,不然会露到外面。这里 policy 用了 AlwaysOn,两条滚动条一直显示,方便看效果。

和 ScrollView 比:ScrollView 开箱即用,但能调的东西不多;Flickable 什么都能自己定,代价是滚动条、裁剪这些都得自己动手。

适用场景:画布、大图预览、需要横向纵向都平移的区域。

ScrollIndicator 指示器

只用于进度指示:

演示代码

qml 复制代码
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts

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

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

        Flickable {
            id: flickable
            Layout.fillWidth: true
            Layout.fillHeight: true
            clip: true  // 防止内容超出边界

            contentWidth: contentRect.width
            contentHeight: contentRect.height

            // 与ScrollBar的区别是不可交互,仅提供视觉指示,
            // ScrollIndicator不能用在ScrollView中,
            // 否则报错:ScrollIndicator must be attached to a Flickable.
            ScrollIndicator.vertical: ScrollIndicator {
                contentItem: Rectangle {
                    implicitWidth: 6
                    color: "#ccc"
                    radius: 3
                }
            }

            Rectangle {
                id: contentRect
                width: 500
                height: 500
                color: "#3498db"
                Text {
                    text: "Scrollable Content"
                    anchors.centerIn: parent
                    font.pointSize: 20
                    color: "#fff"
                }
            }
        }
    }
}

ScrollIndicator 和 ScrollBar 长得很像,但它只能看不能拖,是纯视觉提示用的。它还有个硬性限制:只能附加在 Flickable 上,不能写进 ScrollView 里,硬写会直接报错。

新手最容易把 ScrollBar 和 ScrollIndicator 搞混,记一个判断标准就够了:能拖的叫 ScrollBar,只能看的叫 ScrollIndicator。

适用场景:只读浏览、不想让用户拖进度的翻页式内容。

什么场景用哪个

场景 用哪个
纵向列表,内容包起来就能滚 ScrollView
横竖都要滚,或要自己控制滚动行为 Flickable + ScrollBar
只提示位置,不允许拖动 ScrollIndicator

已验证环境:

相关推荐
小许同学记录成长2 小时前
几何体编辑算法
qt·算法
时间的拾荒人2 小时前
Qt 信号与槽机制详解(二):连接方式详解与面试指南
开发语言·qt·面试
实心儿儿12 小时前
Qt — Qt 事件
开发语言·qt
bkspiderx19 小时前
Qt 的消息机制:事件驱动与信号槽的底层逻辑
开发语言·qt·信号槽·事件驱动·qt 的消息机制
江湖人称菠萝包20 小时前
【Qt】《Qt 5.9 C++开发指南》笔记-Chapter11-数据库
笔记·qt·qt5
励志不掉头发的内向程序员21 小时前
【从零写一个CAD 02】画完第一条线之后:实体容器、Esc 取消,和按了没反应的键盘
开发语言·c++·qt·学习·系统架构
Quz1 天前
QML TreeView:排序与搜索过滤
qt
Quz1 天前
QML TreeView:基础树视图与自定义委托
qt
Junfeng的技术笔记1 天前
基于 C++/Qt 的雷达回波信号检测与测距仿真系统
qt