QScrollArea类和QSroller类的简单介绍

QScrollArea类和QScroller类的简单介绍

在 Qt 中,QScrollArea容器类组件 ,用于为超出显示区域的子部件提供滚动视图;QScroller滚动控制类 ,用于为任意部件(包括 QScrollArea)添加触摸式的弹性滚动、惯性滚动等高级滚动行为。两者常结合使用,但职责不同:

核心作用
QScrollArea 提供基础滚动容器,包含滚动条,可包裹任意 QWidget 实现区域滚动
QScroller 为部件(如 QScrollArea、QListView 等)添加手势 / 触摸滚动(惯性、回弹等)

一、QScorllArea类

1. 核心原理

QScrollArea 包含一个视口(viewport) 和一个滚动条(QScrollBar) ,需要滚动的内容必须放在一个「内容部件(widget)」中,再通过 setWidget() 绑定到 QScrollArea

2. 基本使用步骤

步骤 1:创建 QScrollArea 并设置属性
c++ 复制代码
#include <QApplication>
#include <QScrollArea>
#include <QWidget>
#include <QLabel>
#include <QVBoxLayout>

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);

    // 1. 创建滚动区域
    QScrollArea scrollArea;
    scrollArea.setWindowTitle("QScrollArea 示例");
    scrollArea.resize(400, 300); // 设置滚动区域大小

    // 2. 创建内容部件(承载需要滚动的内容)
    QWidget *contentWidget = new QWidget;
    QVBoxLayout *contentLayout = new QVBoxLayout(contentWidget); // 内容布局

    // 3. 向内容部件添加大量子部件(模拟超出显示区域)
    for (int i = 0; i < 20; ++i) {
        QLabel *label = new QLabel(QString("这是第 %1 行内容").arg(i+1));
        label->setFixedHeight(40); // 固定高度,让内容超出视口
        contentLayout->addWidget(label);
    }

    // 4. 将内容部件绑定到滚动区域
    scrollArea.setWidget(contentWidget);

    // 关键属性设置(可选)
    scrollArea.setWidgetResizable(true); // 内容部件自动适应滚动区域宽度
    scrollArea.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // 隐藏水平滚动条
    scrollArea.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); // 始终显示垂直滚动条

    scrollArea.show();
    return a.exec();
}

代码运行效果:

3. 核心 API 详解

方法 作用
setWidget(QWidget *widget) 设置滚动区域的内容部件(核心)
widget() 获取当前内容部件
setWidgetResizable(bool) 是否让内容部件自动适应滚动区域的视口宽度(默认 false)
setHorizontalScrollBarPolicy 设置水平滚动条策略(如 Qt::ScrollBarAsNeeded/AlwaysOn/AlwaysOff
setVerticalScrollBarPolicy 设置垂直滚动条策略
viewport() 获取滚动区域的视口部件(可自定义绘制)
ensureWidgetVisible(QWidget*) 滚动到指定子部件可见位置
scrollContentsBy(int dx, int dy) 手动滚动内容(dx: 水平偏移,dy: 垂直偏移)

4. 常见场景:自定义滚动内容

如果内容是自定义绘制(而非子部件),可继承 QWidget 重写 paintEvent,再作为内容部件传入:

c++ 复制代码
// 自定义绘制的内容部件
class CustomContent : public QWidget {
protected:
    void paintEvent(QPaintEvent *event) override {
        QPainter painter(this);
        painter.fillRect(rect(), Qt::lightGray);
        // 绘制大量内容(超出视口)
        for (int i = 0; i < 50; ++i) {
            painter.drawText(10, 20 + i*30, QString("自定义绘制行 %1").arg(i+1));
        }
    }
};

// 使用
CustomContent *content = new CustomContent;
content->setFixedSize(500, 1500); // 固定内容大小(超出滚动区域)
scrollArea.setWidget(content);

二、QScorller类

1. 核心作用

QScroller 是 Qt 提供的滚动动力学控制器,支持:

触摸 / 鼠标拖拽滚动;

惯性滚动(松手后继续滚动);

弹性回弹(滚动到边界后回弹);

滚动减速 / 加速控制。

2.基本使用步骤

步骤 1:为 QScrollArea 启用 QScroller
c++ 复制代码
#include "mainwindow.h"
#include <QApplication>
#include <QScrollArea>
#include <QLabel>
#include <QScroller>
#include <QVBoxLayout>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    // MainWindow w;
    // w.show();

    QScrollArea scrollArea;
    scrollArea.setFixedSize(600, 400);
    scrollArea.setAlignment(Qt::AlignCenter);

    QLabel *label = new QLabel();
    label->setPixmap(QPixmap(":/PNG/Image/desktop.png"));   // 1600×900
    label->setScaledContents(true);
    scrollArea.setWidget(label);                  // QScrollArea 接管

    /* 2. 给视口加上惯性滚动(桌面用鼠标,也可 TouchGesture) */
    QScroller::grabGesture(scrollArea.viewport(),
                           QScroller::LeftMouseButtonGesture);

    /* 3. (可选)调参:关闭回弹,加速度大一点 */
    QScroller *scroller = QScroller::scroller(scrollArea.viewport());
    QScrollerProperties prop = scroller->scrollerProperties();
    prop.setScrollMetric(QScrollerProperties::DragVelocitySmoothingFactor, 0.7);
    prop.setScrollMetric(QScrollerProperties::MaximumVelocity, 2000);
    prop.setScrollMetric(QScrollerProperties::OvershootDragResistanceFactor, 0.5);
    scroller->setScrollerProperties(prop);

    scrollArea.show();

    return a.exec();
}

3. QScroller 核心 API 详解

方法 / 枚举 作用
QScroller::scroller(widget) 获取 / 创建指定部件的 QScroller 实例
grabGesture(widget, gesture) 为部件绑定手势(如 LeftMouseButtonGesture 模拟触摸)
setScrollerProperties() 设置滚动属性(回弹、惯性、速度等)
scrollTo(pos) 滚动到指定位置(QPoint 类型)
stop() 停止当前滚动(如惯性滚动)
state() 获取滚动状态(Inactive/Scrolling/Stopping)

4. 常用滚动属性(QScrollerProperties)

滚动度量(ScrollMetric) 作用
OvershootDragFactor 拖拽时的回弹系数(0~1)
OvershootScrollFactor 滚动时的回弹系数(0~1)
DecelerationFactor 惯性减速系数(越小,滚动越容易停止)
MaximumVelocity 最大滚动速度(像素 / 秒)
MinimumVelocity 最小滚动速度(低于此值停止)
SnapPositionX/Y 滚动吸附位置(如网格布局吸附)

三、常见问题与解决方案

1. QScrollArea 内容不滚动

  • 原因:内容部件大小未超出视口,或未设置 setWidget()
  • 解决:确保内容部件 size() 大于 QScrollArea 视口大小,或通过 setFixedSize() 固定内容大小。

2. QScroller 无惯性 / 回弹

  • 原因:未绑定到视口、未启用回弹属性,或内容无滚动空间;

  • 解决:

    cpp 复制代码
    // 确认绑定到视口
    QScroller::scroller(scrollArea.viewport());
    // 启用回弹
    prop.setScrollMetric(QScrollerProperties::OvershootDrag, true);
    prop.setScrollMetric(QScrollerProperties::OvershootScroll, true);

3. 滚动条与 QScroller 冲突

原因:QScrollArea 滚动条默认显示,与 QScroller 手势冲突;

解决:隐藏滚动条(setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff))。

四、总结

适用场景 核心优势
QScrollArea 基础滚动需求(如固定内容、简单滚动) 易用、内置滚动条、支持任意部件
QScroller 高级滚动需求(触摸、惯性、回弹) 支持动力学滚动、跨平台手势

最佳实践

  1. 基础滚动用 QScrollArea
  2. 触摸 / 惯性滚动需求时,为 QScrollArea 的视口绑定 QScroller
  3. 自定义滚动属性时,根据场景调整回弹和惯性系数(移动端偏软,桌面端偏硬)。

参考文章

简单滚动) | 易用、内置滚动条、支持任意部件 |

| QScroller | 高级滚动需求(触摸、惯性、回弹) | 支持动力学滚动、跨平台手势 |

最佳实践

  1. 基础滚动用 QScrollArea
  2. 触摸 / 惯性滚动需求时,为 QScrollArea 的视口绑定 QScroller
  3. 自定义滚动属性时,根据场景调整回弹和惯性系数(移动端偏软,桌面端偏硬)。

参考文章

1.Qt 触控式平滑滚动终极指南:使用 QScroller 实现现代 UI 滚动体验

相关推荐
世转神风-3 小时前
qt-基础打印-不换行打印
开发语言·qt
老歌老听老掉牙4 小时前
PyQt5中RadioButton互斥选择的实现方法
开发语言·python·qt
864记忆5 小时前
Qt Creator 常用命令的中英文对照表
开发语言·qt
Larry_Yanan7 小时前
Qt多进程(六)共享内存和信号量
开发语言·qt
东方忘忧7 小时前
Qt使用QDesktopServices::openUrl打开系统默认应用(如浏览器,文件,文件夹和邮件)
开发语言·qt
计算机内卷的N天7 小时前
qt的模态和非模态状态
开发语言·qt
charlie071 天前
qmake工程不能显示手动配置的Kit
qt
深蓝海拓1 天前
PySide6从0开始学习的笔记(二十) qdarkstyle的深入应用
笔记·python·qt·学习·pyqt
世转神风-1 天前
qt-通信协议基础-double转成QbyteArray-小端系统
开发语言·qt
chao1898441 天前
基于Qt的SSH/FTP远程文件管理与命令执行实现方案
开发语言·qt·ssh