代码流程
在控件初始化的时候,绑定scrollbar的valueChanged信号
// qabstractscrollarea.cpp
void QAbstractScrollAreaPrivate::init()
{
// 省略部分代码
QObject::connect(hbar, SIGNAL(valueChanged(int)), q, SLOT(_q_hslide(int)));
QObject::connect(hbar, SIGNAL(rangeChanged(int,int)), q, SLOT(_q_showOrHideScrollBars()), Qt::QueuedConnection);
scrollBarContainers[Qt::Vertical] = new QAbstractScrollAreaScrollBarContainer(Qt::Vertical, q);
scrollBarContainers[Qt::Vertical]->setObjectName(QLatin1String("qt_scrollarea_vcontainer"));
vbar = scrollBarContainers[Qt::Vertical]->scrollBar;
vbar->setRange(0,0);
scrollBarContainers[Qt::Vertical]->setVisible(false);
vbar->installEventFilter(q);
QObject::connect(vbar, SIGNAL(valueChanged(int)), q, SLOT(_q_vslide(int)));
QObject::connect(vbar, SIGNAL(rangeChanged(int,int)), q, SLOT(_q_showOrHideScrollBars()), Qt::QueuedConnection);
// 省略部分代码
}
void QAbstractScrollAreaPrivate::_q_hslide(int x)
{
Q_Q(QAbstractScrollArea);
int dx = xoffset - x;
xoffset = x;
// 调用子类scrollContentsBy复写的接口
q->scrollContentsBy(dx, 0);
flashScrollBars();
}
qtableview中复写了scrollContentsBy接口(之所以确定是这个函数进行ui刷新,是因为将这个函数复写后空实现,界面滚动后没有任何变化,没有进入paintEvent函数中)
void QTableView::scrollContentsBy(int dx, int dy)
{
// 省略部分代码
d->scrollContentsBy(dx, dy);
// 省略部分代码
}
// 将滚动区域设置为脏区域
inline void scrollContentsBy(int dx, int dy) {
scrollDirtyRegion(dx, dy);
viewport->scroll(dx, dy);
}
// 更新脏区域
inline void scrollDirtyRegion(int dx, int dy) {
scrollDelayOffset = QPoint(-dx, -dy);
updateDirtyRegion();
scrollDelayOffset = QPoint(0, 0);
}
void updateDirtyRegion() {
updateTimer.stop();
viewport->update(updateRegion);
updateRegion = QRegion();
}
qt的ui绘制逻辑是先清空当前脏区域的内容,然后在进行绘制,最终走进paintEvent中。