QAbstractScrollArea 是滚动区域的低级抽象。该区域提供了一个称为视口的中央小部件,该区域的内容将在其中滚动(即内容的可见部分在视口中呈现)。
视口旁边是一个垂直滚动条,下面是一个水平滚动条。当区域中所有内容都显示在视口时,滚动条可以是可见的或隐藏的,具体取决于滚动条的 Qt::ScrollBarPolicy。当滚动条被隐藏时,视口会扩大以覆盖所有可用空间。当滚动条再次可见时,视口会缩小以便为滚动条腾出空间。
可以在视口周围保留一个边距区域 (setViewportMargins())。该功能主要用于在滚动区域上方或旁边放置 QHeaderView 小部件。QAbstractScrollArea 的子类应该实现边距。
在继承 QAbstractScrollArea 时,需要进行以下操作:
一个简单的例子,其中实现了一个可以滚动任何QWidget的滚动区域。使小部件成为视口的子项,这样就不必计算要绘制小部件的哪一部分,而是可以简单地使用 QWidget::move() 移动小部件。当区域内容或视口大小发生变化时,执行以下操作:
QSize areaSize = viewport()->size();
QSize widgetSize = widget->size();
verticalScrollBar()->setPageStep(areaSize.height());
horizontalScrollBar()->setPageStep(areaSize.width());
verticalScrollBar()->setRange(0, widgetSize.height() - areaSize.height());
horizontalScrollBar()->setRange(0, widgetSize.width() - areaSize.width());
updateWidgetPosition();
当滚动条改变值时,需要更新小部件位置,即在视口中找到要绘制的小部件部分:
int hvalue = horizontalScrollBar()->value();
int vvalue = verticalScrollBar()->value();
QPoint topLeft = viewport()->rect().topLeft();
widget->move(topLeft.x() - hvalue, topLeft.y() - vvalue);
为了跟踪滚动条的移动,重新实现虚函数 scrollContentsBy()。为了微调滚动行为,连接到滚动条的 QAbstractSlider::actionTriggered() 信号并根据需要调整 QAbstractSlider::sliderPosition()。
为方便起见,QAbstractScrollArea 使所有视口事件在 viewportEvent() 处理程序中可用。
1、enum QAbstractScrollArea::SizeAdjustPolicy:此枚举指定当视口大小发生变化时滚动区域大小的变化策略。
1、HorizontalScrollBarPolicy : Qt::ScrollBarPolicy
verticalScrollBarPolicy : Qt::ScrollBarPolicy
水平、垂直滚动条的策略。默认策略是 Qt::ScrollBarAsNeeded。
enum Qt::ScrollBarPolicy:
2、sizeAdjustPolicy : SizeAdjustPolicy
当视口大小发生变化时滚动区域大小如何变化的策略。
默认策略是 AdjustIgnored。更改此属性实际上可能会调整滚动区域的大小。
1、void addScrollBarWidget(QWidget *widget, Qt::Alignment alignment)
在 alignment 指定的位置添加小部件作为滚动条小部件。
滚动条小部件显示在水平或垂直滚动条旁边,可以放置在它的任一侧。如果希望滚动条小部件始终可见,将相应滚动条的 scrollBarPolicy 设置为 ScrollBarAlwaysOn。
如果是水平滚动条,alignment 必须是 Qt::Alignleft 和 Qt::AlignRight 之一。
如果是垂直滚动条,alignment 必须是 Qt::AlignTop 和 Qt::AlignBottom 之一。
滚动条小部件将调整大小以适合当前样式的滚动条几何形状。
#include
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QScrollArea * scrollArea = new QScrollArea;
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
auto slider = new QSlider(Qt::Vertical);
slider->setRange(0,1000);
QLabel * label = new QLabel("hello");
label->setFixedHeight(1000);
scrollArea->setWidget(label);
scrollArea->addScrollBarWidget(slider,Qt::AlignTop);
connect(slider,&QSlider::valueChanged,scrollArea->verticalScrollBar(),&QScrollBar::setValue);
QHBoxLayout * hb = new QHBoxLayout(this);
hb->addWidget(scrollArea);
}
QWidgetList scrollBarWidgets(Qt::Alignment alignment)
返回当前设置的滚动条小部件的列表。
2、QScrollBar* horizontalScrollBar() / void setHorizontalScrollBar(QScrollBar *scrollBar)
水平滚动条。
QAbstractScrollArea 默认已经提供水平和垂直滚动条。可以调用此函数将默认的水平滚动条替换为您自己的自定义滚动条。
QScrollBar *verticalScrollBar() / void setVerticalScrollBar(QScrollBar *scrollBar)
垂直滚动条。
3、QSize maximumViewportSize()
视口的大小。
4、【虚函数】void scrollContentsBy(int dx, int dy)
当滚动条被 dx、dy 移动时调用这个处理程序,因此应该相应地滚动视口的内容。
调用此函数以编程方式滚动是错误的,应该改用滚动条(例如,通过直接调用 QScrollBar::setValue())。
5、void setCornerWidget(QWidget *widget)
将两个滚动条之间角落的小部件设置为小部件。
6、void setViewportMargins(int left, int top, int right, int bottom)
设置滚动区域周围的边距。边缘空间留空。小部件将放在未使用的区域。
这个函数一般被 QTreeView 和 QTableView 调用。
7、bool viewportEvent(QEvent *event)
滚动区域的主要事件处理程序(viewport() 小部件)。
返回 true 向事件系统表明该事件已被处理,不需要进一步处理; 否则返回 false 以指示应进一步传播该事件。
可以在子类中重新实现此函数,但建议使用专门的事件处理程序。
QScrollArea 类继承自 QAbstractScrollArea 。提供一个滚动视图小部件。用于在框架内显示子窗口小部件的内容。如果小部件超过框架的大小,视图可以提供滚动条,以便可以查看子小部件的整个区域。
1、alignment : Qt::Alignment
滚动区域小部件的对齐方式,有效值是以下标志的组合:
- Qt::AlignLeft
- Qt::AlignHCenter
- Qt::AlignRight
- Qt::AlignTop
- Qt::AlignVCenter
- Qt::AlignBottom
默认情况下,小部件保持在滚动区域的左上角。
2、widgetResizable : bool
是否应调整视图小部件的大小。
如果为 false(默认值),则滚动区域遵循其小部件的大小。
如果为 true,则滚动区域将自动调整小部件的大小,以充分利用额外的空间。
不管这个属性如何,都可以使用 widget()->resize() 以编程方式调整小部件的大小,滚动区域将自动调整到新的大小。
1、void ensureVisible(int x, int y, int xmargin = 50, int ymargin = 50)
滚动滚动区域的内容,使点 (x, y) 在视口区域内可见,其边距由 xmargin 和 ymargin 指定,以像素为单位。如果无法到达指定点,则将内容滚动到最近的有效位置。
2、void ensureWidgetVisible(QWidget *childWidget, int xmargin = 50, int ymargin = 50)
滚动滚动区域的内容,以便 widget() 的 子部件 childWidget 在视口内可见,其边距由 xmargin 和 ymargin 以像素为单位指定。如果无法到达指定点,则将内容滚动到最近的有效位置。
3、void setWidget(QWidget *widget) / QWidget * widget()
滚动区域的小部件。
小部件成为滚动区域的子级,并在删除滚动区域或设置新的小部件时被销毁。
小部件的 autoFillBackground 属性将设置为 true。
如果添加小部件时滚动区域(this)可见,则必须显式调用 show()。
必须在调用此函数之前添加小部件的布局,否则该小部件将不可见。
4、QWidget * takeWidget()
删除滚动区域的小部件,并将小部件的所有权传递给调用者。