Qt中通过触摸或鼠标实现scroller滚动
Qt 5.9.1
通常我们在使用QTreeWidget,QTableWidget,QListWidget等支持内容滚动的控件时,都是通过控件右边的滚动条来实现滚动(当然也可以通过鼠标滚轮来实现滚动),但是在一些移动平台上就显的不那么方便了,可能我们更需要像安卓app上通过手势来实现滚动。
1.滚动相关类
1.1 QScroller
QScroller类为支持滚动的小部件或视图启用滚动。
通过滚动,用户可以沿给定方向推动小部件,并且它将继续沿该方向滚动,直到由用户或通过摩擦停止。 可以改变惯性,摩擦和其他物理量,以微调直观的用户体验。
QScroller对象是存储当前位置和滚动速度的对象,负责更新。 QScroller可以通过手势触发
每当滚动器需要更新其几何信息时,滚动的QObject接收QScrollPrepareEvent
,每当实际滚动对象的内容时,都会接收QScrollEvent
。
滚动条使用全局QAbstractAnimation
计时器生成其QScrollEvents
。 这可以使用QScrollerProperties :: FrameRate
在每个QScroller
的基础上更改。
scroller examples目录中的几个示例显示了如何使用QScroller
,QScrollEvent
和滚动条手势。
尽管此动态卷轴通过QScrollerProperties
提供了大量设置,但我们建议您将它们全部保留为默认的平台优化值。 在更改它们之前,您可以在scroller examples目录中试验绘图示例。
1.1.1 QScroller::Input
此枚举包含与QScroller相关输入设备的输入事件。
Constant | Value | Description |
---|---|---|
QScroller::InputPress | 1 | The user pressed the input device (e.g. QEvent::MouseButtonPress, QEvent::GraphicsSceneMousePress, QEvent::TouchBegin) |
QScroller::InputMove | 2 | The user moved the input device (e.g. QEvent::MouseMove, QEvent::GraphicsSceneMouseMove, QEvent::TouchUpdate) |
QScroller::InputRelease | 3 | The user released the input device (e.g. QEvent::MouseButtonRelease, QEvent::GraphicsSceneMouseRelease, QEvent::TouchEnd) |
1.1.2 QScroller::ScrollerGestureType
此枚举包含QScroller手势识别器支持的不同手势类型。
Constant | Value | Description |
---|---|---|
QScroller::TouchGesture | 0 | 手势识别器仅在触摸事件时触发。 具体而言,当使用触摸屏和使用触摸板时的双触摸点时,它将对触摸点作出反应。 |
QScroller::LeftMouseButtonGesture | 1 | 手势识别器仅在左鼠标按钮事件上触发。 |
QScroller::MiddleMouseButtonGesture | 3 | 手势识别器仅在鼠标中键事件上触发。 |
QScroller::RightMouseButtonGesture | 2 | 手势识别器仅在鼠标右键事件上触发。 |
1.1.3 QScroller::State
此枚举包含不同的QScroller状态。
Constant | Value | Description |
---|---|---|
QScroller::Inactive | 0 | scroller不滚动,没有任何按下。 |
QScroller::Pressed | 1 | 收到触摸事件或按下了鼠标按钮但当前未拖动滚动区域。 |
QScroller::Dragging | 2 | 滚动区域当前跟随触摸点或鼠标。 |
QScroller::Scrolling | 3 | 滚动区域正在自行移动。 |
1.2 QScrollerProperties
QScrollerProperties类存储QScroller的设置。
QScrollerProperties类存储QScroller使用的参数。
默认设置取决于平台,因此Qt模拟动态滚动的平台行为。
作为惯例,QScrollerProperties以物理单位(米,秒)为单位,并由QScroller使用当前DPI进行转换。
1.2.1 QScrollerProperties::FrameRates
此枚举描述了拖动或滚动时可用帧速率。
Constant | Value | Description |
---|---|---|
QScrollerProperties::Fps60 | 1 | 60 frames per second |
QScrollerProperties::Fps30 | 2 | 30 frames per second |
QScrollerProperties::Fps20 | 3 | 20 frames per second |
QScrollerProperties::Standard | 0 | the default value is 60 frames per second (which corresponds to QAbstractAnimation). |
1.2.2 QScrollerProperties::OvershootPolicy
这个枚举描述了各种过冲模式。
Constant | Value | Description |
---|---|---|
QScrollerProperties::OvershootWhenScrollable | 0 | 当内容可滚动时,可以进行过冲。 这是默认值。 |
QScrollerProperties::OvershootAlwaysOff | 1 | 即使内容可滚动,也永远不会启用过冲。 |
QScrollerProperties::OvershootAlwaysOn | 2 | 即使内容不可滚动,也始终启用过冲。 |
1.2.3 QScrollerProperties::ScrollMetric
此枚举包含不同的滚动度量类型。 如果没有另外指出,setScrollMetric函数需要QVariant类型。
有关不同值背后概念的更多详细信息,请参阅QScroller文档。
Constant | Value | Description |
---|---|---|
QScrollerProperties::MousePressEventDelay | 0 | 这是在[s]中开始滑动手势时鼠标按下事件延迟的时间。 如果在该时间内触发手势,则不向滚动对象发送鼠标按下或释放。 如果在该延迟之后触发,则发送延迟鼠标按下加上全局位置QPoint(-QWIDGETSIZE_MAX,-QWIDGETSIZE_MAX)处的伪造释放事件。 如果手势被取消,则发送延迟鼠标按下加上真实释放事件。 |
QScrollerProperties::DragStartDistance | 1 | 这是在以m为单位触发轻弹手势之前需要移动触摸或鼠标点的最小距离。 |
QScrollerProperties::DragVelocitySmoothingFactor | 2 | 描述实际滚动速度中的程度值。 此值应介于0和1之间。值越小,拖动速度的平滑度越高。 |
QScrollerProperties::AxisLockThreshold | 3 | 如果移动位于一个轴的角度内,则将移动限制为一个轴。 阈值必须在0到1的范围内。 |
QScrollerProperties::ScrollingCurve | 4 | 在用户启动滑动后减速滚动速度时使用QEasingCurve。 请注意,这是位置的缓和曲线,而不是速度:默认值为QEasingCurve::OutQuad,导致速度线性下降(一阶导数)和恒定减速度(二阶导数)。 |
QScrollerProperties::DecelerationFactor | 5 | 此因素会影响滚动条减速到0速度所需的时间。 实际值取决于所选的ScrollingCurve。 对于大多数类型,该值应在0.1到2.0的范围内。 |
QScrollerProperties::MinimumVelocity | 6 | 开始滚动后结束触摸或释放鼠标所需的最小速度(m / s)。 |
QScrollerProperties::MaximumVelocity | 7 | 达到的最大速度(m / s)。 |
QScrollerProperties::MaximumClickThroughVelocity | 8 | 这是点击的最大允许滚动速度,单位为m / s。 这意味着单击当前(缓慢)滚动对象不仅会停止滚动,而且还会将click事件传递给UI控件。 这在使用指数型滚动曲线时很有用。 |
QScrollerProperties::AcceleratingFlickMaximumTime | 9 | 可被识别为加速滑动手势的最长时间(以秒为单位)。如果设置为零,则不检测到这样的手势。 “加速滑动”是在已经滚动的对象上执行的手势。在这种情况下,滚动速度乘以AcceleratingFlickSpeedupFactor来加速它。 |
QScrollerProperties::AcceleratingFlickSpeedupFactor | 10 | 如果检测到加速滑动,则将当前速度乘以该数字。 应该> = 1。 |
QScrollerProperties::SnapPositionRatio | 11 | 这是用户必须在两个捕捉点之间拖动区域以将其捕捉到下一个位置的距离。 0.33表示滚动必须仅达到两个捕捉点之间距离的三分之一,以捕捉到下一个捕捉点。 比率必须介于0和1之间。 |
QScrollerProperties::SnapTime | 12 | 这是滚动曲线的时间因素。 较低的值意味着滚动将花费更长时间。 滚动距离与该值无关。 |
QScrollerProperties::OvershootDragResistanceFactor | 13 | 此值是鼠标拖动和实际滚动区域移动之间的因子(在过冲期间)。 因子必须介于0和1之间。 |
QScrollerProperties::OvershootDragDistanceFactor | 14 | 这是拖动时过冲运动的最大距离。 通过将此值乘以滚动对象的视口大小来计算实际过冲距离。 因子必须介于0和1之间。 |
QScrollerProperties::OvershootScrollDistanceFactor | 15 | 这是滚动时过冲运动的最大距离。 通过将此值乘以滚动对象的视口大小来计算实际过冲距离。 因子必须介于0和1之间。 |
QScrollerProperties::OvershootScrollTime | 16 | 这是用于播放完整过冲动画的时间(以秒为单位)。 |
QScrollerProperties::HorizontalOvershootPolicy | 17 | 这是水平过冲策略(参见OvershootPolicy)。 |
QScrollerProperties::VerticalOvershootPolicy | 18 | 这是垂直过冲策略(参见OvershootPolicy)。 |
QScrollerProperties::FrameRate | 19 | 这是拖动或滚动时应使用的帧速率。 QScroller在内部使用QAbstractAnimation计时器将所有滚动操作同步到可能同时处于活动状态的其他动画。 如果每秒60帧的标准值太快,可以使用此设置降低,同时仍然与QAbstractAnimation同步。 请注意,此处仅允许FrameRates枚举的值。 |
QScrollerProperties::ScrollMetricCount | 20 | This is always the last entry. |
2.相关接口
2.1QAbstractItemView提供的接口
void setVerticalScrollMode(ScrollMode mode)
void setHorizontalScrollMode(ScrollMode mode)
描述滚动条的行为方式。 将滚动模式设置为ScrollPerPixel时,除非使用setSingleStep()显式设置,否则单步长度将自动调整。 通过将单步长度设置为-1可以恢复自动调整。
Constant | Value | Description |
---|---|---|
QAbstractItemView::ScrollPerItem | 0 | 按一个Item滚动 |
QAbstractItemView::ScrollPerPixel | 1 | 按像素滚动 |
2.2 QScroller提供的接口
static Qt::GestureType QScroller::grabGesture(QObject *target,ScrollerGestureType scrollGestureType = TouchGesture)
注册自定义滚动手势识别器,为目标抓取它并返回生成的手势类型。 如果scrollGestureType设置为TouchGesture,则手势会触发触摸事件。 如果将其设置为LeftMouseButtonGesture
,RightMouseButtonGesture
或MiddleMouseButtonGesture
之一,则会触发相应按钮的鼠标事件。
一次只能在一个对象上激活一个滚动手势。 如果在同一个对象上调用此函数两次,它将在抓取新手势之前取消现有手势。
注意:为避免不必要的副作用,触发手势时会发送鼠标事件。 由于未使用初始鼠标按下事件,因此手势会在全局位置(INT_MIN,INT_MIN)发送虚假鼠标释放事件。 这可确保接收原始鼠标按下的窗口小部件的内部状态是一致的。
static Qt::GestureType QScroller::grabbedGesture(QObject *target)
返回当前为目标抓取的手势类型,如果没有抓取手势,则返回0。
3.使用案例
在界面上拖入QTreeWidget,QListWidget和QTableWidget
添加一下代码
QScroller::grabGesture(ui->listWidget,QScroller::LeftMouseButtonGesture);//TouchGesture
QScroller::grabGesture(ui->treeWidget,QScroller::LeftMouseButtonGesture);
ui->tableWidget->setVerticalScrollMode(QListWidget::ScrollPerPixel);
ui->tableWidget->setHorizontalScrollMode(QListWidget::ScrollPerPixel);
QScroller::grabGesture(ui->tableWidget,QScroller::LeftMouseButtonGesture);