116QScrollArea::QScrollArea(QScrollAreaPrivate &dd, QWidget *parent)
117 : QAbstractScrollArea(dd, parent)
120 d->viewport->setBackgroundRole(QPalette::NoRole);
121 const auto singleStep = d->defaultSingleStep();
122 d->vbar->setSingleStep(singleStep);
123 d->hbar->setSingleStep(singleStep);
136void QScrollAreaPrivate::updateWidgetPosition()
139 Qt::LayoutDirection dir = q->layoutDirection();
140 QRect scrolled = QStyle::visualRect(dir, viewport->rect(), QRect(QPoint(-hbar->value(), -vbar->value()), widget->size()));
141 QRect aligned = QStyle::alignedRect(dir, alignment, widget->size(), viewport->rect());
142 widget->move(widget->width() < viewport->width() ? aligned.x() : scrolled.x(),
143 widget->height() < viewport->height() ? aligned.y() : scrolled.y());
146void QScrollAreaPrivate::updateScrollBars()
151 QSize p = viewport->size();
152 QSize m = q->maximumViewportSize();
154 QSize min = qSmartMinSize(widget);
155 QSize max = qSmartMaxSize(widget);
158 if ((widget->layout() ? widget->layout()->hasHeightForWidth() : widget->sizePolicy().hasHeightForWidth())) {
159 QSize p_hfw = p.expandedTo(min).boundedTo(max);
160 int h = widget->heightForWidth(p_hfw.width());
164 if (vbarpolicy == Qt::ScrollBarAsNeeded) {
165 int vbarWidth = vbar->sizeHint().width();
166 QSize m_hfw = m.expandedTo(min).boundedTo(max);
168 if (widget->heightForWidth(m_hfw.width() - vbarWidth) <= m.height()) {
169 while (h > m.height() && vbarWidth) {
172 h = widget->heightForWidth(m_hfw.width());
175 max = QSize(m_hfw.width(), qMax(m_hfw.height(), h));
177 min = QSize(p_hfw.width(), qMax(p_hfw.height(), h));
181 if ((resizable && m.expandedTo(min) == m && m.boundedTo(max) == m)
182 || (!resizable && m.expandedTo(widget->size()) == m))
186 widget->resize(p.expandedTo(min).boundedTo(max));
187 QSize v = widget->size();
189 hbar->setRange(0, v.width() - p.width());
190 hbar->setPageStep(p.width());
191 vbar->setRange(0, v.height() - p.height());
192 vbar->setPageStep(p.height());
193 updateWidgetPosition();
232void QScrollArea::setWidget(QWidget *widget)
235 if (widget == d->widget || !widget)
240 d->hbar->setValue(0);
241 d->vbar->setValue(0);
242 if (widget->parentWidget() != d->viewport)
243 widget->setParent(d->viewport);
244 if (!widget->testAttribute(Qt::WA_Resized))
245 widget->resize(widget->sizeHint());
247 d->widget->setAutoFillBackground(
true);
248 widget->installEventFilter(
this);
249 d->widgetSize = QSize();
250 d->updateScrollBars();
349QSize QScrollArea::sizeHint()
const
351 Q_D(
const QScrollArea);
352 int f = 2 * d->frameWidth;
354 int h = fontMetrics().height();
356 if (!d->widgetSize.isValid())
357 d->widgetSize = d->resizable ? d->widget->sizeHint() : d->widget->size();
360 sz += QSize(12 * h, 8 * h);
362 if (d->vbarpolicy == Qt::ScrollBarAlwaysOn)
363 sz.setWidth(sz.width() + d->vbar->sizeHint().width());
364 if (d->hbarpolicy == Qt::ScrollBarAlwaysOn)
365 sz.setHeight(sz.height() + d->hbar->sizeHint().height());
366 return sz.boundedTo(QSize(36 * h, 24 * h));
402void QScrollArea::ensureVisible(
int x,
int y,
int xmargin,
int ymargin)
406 int logicalX = QStyle::visualPos(layoutDirection(), d->viewport->rect(), QPoint(x, y)).x();
408 if (logicalX - xmargin < d->hbar->value()) {
409 d->hbar->setValue(qMax(0, logicalX - xmargin));
410 }
else if (logicalX > d->hbar->value() + d->viewport->width() - xmargin) {
411 d->hbar->setValue(qMin(logicalX - d->viewport->width() + xmargin, d->hbar->maximum()));
414 if (y - ymargin < d->vbar->value()) {
415 d->vbar->setValue(qMax(0, y - ymargin));
416 }
else if (y > d->vbar->value() + d->viewport->height() - ymargin) {
417 d->vbar->setValue(qMin(y - d->viewport->height() + ymargin, d->vbar->maximum()));
432void QScrollArea::ensureWidgetVisible(QWidget *childWidget,
int xmargin,
int ymargin)
436 if (!d->widget->isAncestorOf(childWidget))
439 const QRect microFocus = childWidget->inputMethodQuery(Qt::ImCursorRectangle).toRect();
440 const QRect defaultMicroFocus =
441 childWidget->QWidget::inputMethodQuery(Qt::ImCursorRectangle).toRect();
442 QRect focusRect = (microFocus != defaultMicroFocus)
443 ? QRect(childWidget->mapTo(d->widget, microFocus.topLeft()), microFocus.size())
444 : QRect(childWidget->mapTo(d->widget, QPoint(0,0)), childWidget->size());
445 const QRect visibleRect(-d->widget->pos(), d->viewport->size());
447 if (visibleRect.contains(focusRect))
450 focusRect.adjust(-xmargin, -ymargin, xmargin, ymargin);
452 if (focusRect.width() > visibleRect.width())
453 d->hbar->setValue(focusRect.center().x() - d->viewport->width() / 2);
454 else if (focusRect.right() > visibleRect.right())
455 d->hbar->setValue(focusRect.right() - d->viewport->width() + 1);
456 else if (focusRect.left() < visibleRect.left())
457 d->hbar->setValue(focusRect.left());
459 if (focusRect.height() > visibleRect.height())
460 d->vbar->setValue(focusRect.center().y() - d->viewport->height() / 2);
461 else if (focusRect.bottom() > visibleRect.bottom())
462 d->vbar->setValue(focusRect.bottom() - d->viewport->height() + 1);
463 else if (focusRect.top() < visibleRect.top())
464 d->vbar->setValue(focusRect.top());