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 滚动体验

相关推荐
用户805533698031 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner1 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz6 天前
QML Hello World 入门示例
qt
xcyxiner9 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner10 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner10 天前
DicomViewer (添加模型类)3
qt
xcyxiner11 天前
DicomViewer (目录调整) 2
qt
xcyxiner11 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
桥田智能13 天前
桥田智能 QT-650S:面向白车身焊装的 800kg 重载快换解决方案
开发语言·qt·系统架构
森G13 天前
75、服务器源码解析---------云视频服务项目
linux·服务器·网络·c++·qt