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 | 高级滚动需求(触摸、惯性、回弹) | 支持动力学滚动、跨平台手势 |
最佳实践:
- 基础滚动用
QScrollArea; - 触摸 / 惯性滚动需求时,为
QScrollArea的视口绑定QScroller; - 自定义滚动属性时,根据场景调整回弹和惯性系数(移动端偏软,桌面端偏硬)。
参考文章
简单滚动) | 易用、内置滚动条、支持任意部件 |
| QScroller | 高级滚动需求(触摸、惯性、回弹) | 支持动力学滚动、跨平台手势 |
最佳实践:
- 基础滚动用
QScrollArea; - 触摸 / 惯性滚动需求时,为
QScrollArea的视口绑定QScroller; - 自定义滚动属性时,根据场景调整回弹和惯性系数(移动端偏软,桌面端偏硬)。
参考文章