1.update()
void QWidget::update()
{
update(rect());
}
void QWidget::update(const QRect &rect)
{
Q_D(QWidget);
d->update(rect);
}
template <typename T>
void QWidgetPrivate::update(T r)
{
Q_Q(QWidget);
if (!q->isVisible() || !q->updatesEnabled())
return;
T clipped = r & q->rect();
if (clipped.isEmpty())
return;
if (q->testAttribute(Qt::WA_WState_InPaintEvent)) {
QCoreApplication::postEvent(q, new QUpdateLaterEvent(clipped));
return;
}
QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
if (tlwExtra && tlwExtra->backingStore)
tlwExtra->repaintManager->markDirty(clipped, q);
}
void QWidgetRepaintManager::markDirty(const T &r, QWidget *widget, UpdateTime updateTime, BufferState bufferState)
{
qCInfo(lcWidgetPainting) << "Marking" << r << "of" << widget << "dirty"
<< "with" << updateTime;
Q_ASSERT(tlw->d_func()->extra);
Q_ASSERT(tlw->d_func()->extra->topextra);
Q_ASSERT(widget->isVisible() && widget->updatesEnabled());
Q_ASSERT(widget->window() == tlw);
Q_ASSERT(!r.isEmpty());
#if QT_CONFIG(graphicseffect)
widget->d_func()->invalidateGraphicsEffectsRecursively();
#endif
QRect widgetRect = widgetRectFor(widget, r);
// ---------------------------------------------------------------------------
if (widget->d_func()->shouldPaintOnScreen()) {
if (widget->d_func()->dirty.isEmpty()) {
widget->d_func()->dirty = r;
sendUpdateRequest(widget, updateTime);
return;
} else if (qt_region_strictContains(widget->d_func()->dirty, widgetRect)) {
if (updateTime == UpdateNow)
sendUpdateRequest(widget, updateTime);
return; // Already dirty
}
const bool eventAlreadyPosted = !widget->d_func()->dirty.isEmpty();
widget->d_func()->dirty += r;
if (!eventAlreadyPosted || updateTime == UpdateNow)
sendUpdateRequest(widget, updateTime);
return;
}
// ---------------------------------------------------------------------------
if (QWidgetPrivate::get(widget)->renderToTexture) {
if (!widget->d_func()->inDirtyList)
addDirtyRenderToTextureWidget(widget);
if (!updateRequestSent || updateTime == UpdateNow)
sendUpdateRequest(tlw, updateTime);
return;
}
// ---------------------------------------------------------------------------
QRect effectiveWidgetRect = widget->d_func()->effectiveRectFor(widgetRect);
const QPoint offset = widget->mapTo(tlw, QPoint());
QRect translatedRect = effectiveWidgetRect.translated(offset);
#if QT_CONFIG(graphicseffect)
// Graphics effects may exceed window size, clamp
translatedRect = translatedRect.intersected(QRect(QPoint(), tlw->size()));
#endif
if (qt_region_strictContains(dirty, translatedRect)) {
if (updateTime == UpdateNow)
sendUpdateRequest(tlw, updateTime);
return; // Already dirty
}
// ---------------------------------------------------------------------------
if (bufferState == BufferInvalid) {
const bool eventAlreadyPosted = !dirty.isEmpty() || updateRequestSent;
#if QT_CONFIG(graphicseffect)
if (widget->d_func()->graphicsEffect)
dirty += widget->d_func()->effectiveRectFor(r).translated(offset);
else
#endif
dirty += r.translated(offset);
if (!eventAlreadyPosted || updateTime == UpdateNow)
sendUpdateRequest(tlw, updateTime);
return;
}
// ---------------------------------------------------------------------------
if (dirtyWidgets.isEmpty()) {
addDirtyWidget(widget, r);
sendUpdateRequest(tlw, updateTime);
return;
}
// ---------------------------------------------------------------------------
if (widget->d_func()->inDirtyList) {
if (!qt_region_strictContains(widget->d_func()->dirty, effectiveWidgetRect)) {
#if QT_CONFIG(graphicseffect)
if (widget->d_func()->graphicsEffect)
widget->d_func()->dirty += widget->d_func()->effectiveRectFor(r);
else
#endif
widget->d_func()->dirty += r;
}
} else {
addDirtyWidget(widget, r);
}
// ---------------------------------------------------------------------------
if (updateTime == UpdateNow)
sendUpdateRequest(tlw, updateTime);
}
template void QWidgetRepaintManager::markDirty<QRect>(const QRect &, QWidget *, UpdateTime, BufferState);
template void QWidgetRepaintManager::markDirty<QRegion>(const QRegion &, QWidget *, UpdateTime, BufferState);
void QWidgetRepaintManager::addDirtyWidget(QWidget *widget, const QRegion &rgn)
{
if (widget && !widget->d_func()->inDirtyList && !widget->data->in_destructor) {
QWidgetPrivate *widgetPrivate = widget->d_func();
#if QT_CONFIG(graphicseffect)
if (widgetPrivate->graphicsEffect)
widgetPrivate->dirty = widgetPrivate->effectiveRectFor(rgn.boundingRect());
else
#endif // QT_CONFIG(graphicseffect)
widgetPrivate->dirty = rgn;
dirtyWidgets.append(widget);
widgetPrivate->inDirtyList = true;
}
}
update()函数并不立即执行刷新。
2.void repaint();
void QWidget::repaint()
{
repaint(rect());
}
void QWidget::repaint(const QRect &rect)
{
Q_D(QWidget);
d->repaint(rect);
}
void QWidgetPrivate::repaint(T r)
{
Q_Q(QWidget);
if (!q->isVisible() || !q->updatesEnabled() || r.isEmpty())
return;
QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
if (tlwExtra && tlwExtra->backingStore)
tlwExtra->repaintManager->markDirty(r, q, QWidgetRepaintManager::UpdateNow);
}
repaint()函数为立即刷新。
3.void scroll(int dx, int dy);
void QWidget::scroll(int dx, int dy)
{
if ((!updatesEnabled() && children().size() == 0) || !isVisible())
return;
if (dx == 0 && dy == 0)
return;
Q_D(QWidget);
#if QT_CONFIG(graphicsview)
if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) {
// Graphics View maintains its own dirty region as a list of rects;
// until we can connect item updates directly to the view, we must
// separately add a translated dirty region.
for (const QRect &rect : d->dirty)
proxy->update(rect.translated(dx, dy));
proxy->scroll(dx, dy, proxy->subWidgetRect(this));
return;
}
#endif
d->setDirtyOpaqueRegion();
d->scroll_sys(dx, dy);
}
void QWidgetPrivate::scroll_sys(int dx, int dy)
{
Q_Q(QWidget);
scrollChildren(dx, dy);
scrollRect(q->rect(), dx, dy);
}
void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy)
{
Q_Q(QWidget);
QWidget *tlw = q->window();
QTLWExtra* x = tlw->d_func()->topData();
QWidgetRepaintManager *repaintManager = x->repaintManager.get();
if (!repaintManager)
return;
static const bool accelEnv = qEnvironmentVariableIntValue("QT_NO_FAST_SCROLL") == 0;
const QRect clipR = clipRect();
const QRect scrollRect = rect & clipR;
const bool accelerateScroll = accelEnv && isOpaque && !q_func()->testAttribute(Qt::WA_WState_InPaintEvent);
if (!accelerateScroll) {
if (!overlappedRegion(scrollRect.translated(data.crect.topLeft()), true).isEmpty()) {
QRegion region(scrollRect);
subtractOpaqueSiblings(region);
invalidateBackingStore(region);
}else {
invalidateBackingStore(scrollRect);
}
} else {
const QPoint toplevelOffset = q->mapTo(tlw, QPoint());
const QRect destRect = scrollRect.translated(dx, dy) & scrollRect;
const QRect sourceRect = destRect.translated(-dx, -dy);
const QRegion overlappedExpose = (overlappedRegion(scrollRect.translated(data.crect.topLeft())))
.translated(-data.crect.topLeft()) & clipR;
QRegion childExpose(scrollRect);
const qreal factor = QHighDpiScaling::factor(q->windowHandle());
if (overlappedExpose.isEmpty() || qFloor(factor) == factor) {
const QList<QRect> rectsToScroll =
getSortedRectsToScroll(QRegion(sourceRect) - overlappedExpose, dx, dy);
for (const QRect &r : rectsToScroll) {
if (repaintManager->bltRect(r, dx, dy, q)) {
childExpose -= r.translated(dx, dy);
}
}
}
childExpose -= overlappedExpose;
if (inDirtyList) {
if (rect == q->rect()) {
dirty.translate(dx, dy);
} else {
QRegion dirtyScrollRegion = dirty.intersected(scrollRect);
if (!dirtyScrollRegion.isEmpty()) {
dirty -= dirtyScrollRegion;
dirtyScrollRegion.translate(dx, dy);
dirty += dirtyScrollRegion;
}
}
}
if (!q->updatesEnabled())
return;
if (!overlappedExpose.isEmpty())
invalidateBackingStore(overlappedExpose);
if (!childExpose.isEmpty()) {
repaintManager->markDirty(childExpose, q);
isScrolled = true;
}
// Instead of using native scroll-on-screen, we copy from
// backingstore, giving only one screen update for each
// scroll, and a solid appearance
repaintManager->markNeedsFlush(q, destRect, toplevelOffset);
}
}
|