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

已验证环境:

相关推荐
沫璃染墨1 天前
《Qt从零入门系列(十四):QThread多线程详解——从线程创建到客户端阻塞处理》
开发语言·c++·笔记·qt·ui·交互·线程
代钦塔拉1 天前
【C++/Qt 进阶】设计模式系列(5):适配器模式——给“不兼容的接口“贴一层翻译膜
c++·qt·设计模式
把我格子衫拿来1 天前
VTK 9.5 与 Qt 6 联合开发:从嵌入三维窗口到可维护的桌面架构
c++·python·qt·vtk·三维可视化
把我格子衫拿来2 天前
VTK 与 Qt 的 CMake 工程怎么组织?模块、工具链与二进制兼容排错
c++·qt·vtk·cmake·工程实践
代钦塔拉2 天前
【C++/Qt 进阶】设计模式系列(4):原型模式——用“克隆“代替“重新构造“
c++·qt·设计模式
Python图像识别2 天前
56-【2027毕设】YOLO11X光安检危险物品检测系统 - Python完整源码+PyQt5界面+训练模型+数据集
python·qt·课程设计
把我格子衫拿来2 天前
鼠标点到哪里才算选中?Qt 与 VTK 的拾取坐标、DPI 与体素定位
python·qt·vtk·坐标变换·三维交互
Lhan.zzZ2 天前
Qt WebEngineView 在 Linux 上无法加载网页:从“看不见 HTML“到“禁用沙箱“
linux·c++·qt
Quz3 天前
QML TabBar 标签栏交互效果合集
qt·动画·qml
zhanghaha13143 天前
Qt 工程实例:逐词逐句保姆级讲解
qt