fix: wheel event not propagating to parent in Qt6 - #770
Draft
18202781743 wants to merge 1 commit into
Draft
Conversation
Qt6 QApplication::notify pre-accepts wheel events (we.setAccepted(true)) before delivery. If a widget's wheelEvent doesn't call the parent class (which would ignore() the event), the event stays accepted and does not propagate to parent widgets (e.g. QScrollArea). This differs from Qt5 where unhandled wheel events propagated by default. Fix by overriding wheelEvent in DSpinBox, DDoubleSpinBox, DComboBox following the pattern from commit fe16c8e (settings/ComboBox): - hasFocus(): call base class wheelEvent (stepBy + accept, default behavior) - no focus: call QWidget::wheelEvent (ignore() -> event propagates) For DSlider, which is a QWidget containing an inner QSlider with an eventFilter on qApp, fix the eventFilter instead: when the inner slider has no focus, call e->ignore() before returning true so the event propagates to the parent scrollarea in Qt6. This fixes the Qt6-specific regression where scrolling over spinbox / combobox / slider inside a scrollarea was blocked. Ref: DDE-72
Contributor
|
Skipping CI for Draft Pull Request. |
Contributor
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: 18202781743 The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
Reviewer's GuideThis PR adjusts wheel event handling for DSpinBox, DDoubleSpinBox, DComboBox, and DSlider so that mouse wheel scrolling only affects the control when it has focus and otherwise propagates to parent scroll areas, restoring Qt5-like behavior under Qt6. Sequence diagram for wheel event handling with focus-dependent propagationsequenceDiagram
actor User
participant DSpinBox
participant QSpinBox
participant QWidget
participant QScrollArea
User->>DSpinBox: wheelEvent
alt hasFocus
DSpinBox->>QSpinBox: wheelEvent(event)
QSpinBox-->>DSpinBox: accept
DSpinBox-->>User: value changed
else noFocus
DSpinBox->>QWidget: wheelEvent(event)
QWidget-->>DSpinBox: ignore
DSpinBox-->>QScrollArea: wheelEvent
QScrollArea-->>User: scroll page
end
Sequence diagram for DSlider eventFilter wheel event propagationsequenceDiagram
actor User
participant DSlider
participant SpecialSlider
participant QScrollArea
User->>SpecialSlider: wheelEvent
SpecialSlider->>DSlider: eventFilter(watched,e)
alt mouseWheelEnabled and hasFocus
DSlider-->>SpecialSlider: return false
SpecialSlider-->>User: QSlider::wheelEvent handles
else notEnabled or noFocus
DSlider->>SpecialSlider: e->ignore()
DSlider-->>SpecialSlider: return true
SpecialSlider-->>QScrollArea: wheelEvent
QScrollArea-->>User: scroll page
end
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
背景 / Background
Qt6 的
QApplication::notify在派发 wheel event 前执行we.setAccepted(true)。若控件的wheelEvent不调用父类事件函数(最终event->ignore()),事件将保持 accepted 状态,不会向父控件(如QScrollArea)传播——这与 Qt5 行为不一致(Qt5 中未处理的滚轮事件默认可传播)。导致所有 dtk6widget 应用中,位于
QScrollArea/DScrollArea内的DSpinBox/DDoubleSpinBox/DComboBox/DSlider在鼠标悬停滚动时会阻断页面滚动(值被误改 / 选项被切换,但页面不滚动)。复现场景:打印预览高级设置、设置对话框、examples/collections示例等。根因 / Root Cause
DSpinBox(继承QSpinBox)、DDoubleSpinBox(继承QDoubleSpinBox)、DComboBox(继承QComboBox)均未重写wheelEvent,沿用各自基类的wheelEvent(调用stepBy()/ 切项 +event->accept()),在 Qt6 下事件被 accept 后不传播。DSlider继承结构不同:继承QWidget,内部持有SpecialSlider : public QSlider,并通过qApp->installEventFilter拦截内部 slider 的滚轮事件,原逻辑在 Qt6 下同样阻断传播。settings/ComboBox::wheelEvent):有焦点时调基类wheelEvent,无焦点时return QWidget::wheelEvent(e)(即ignore())让事件传播。改动 / Changes
沿用
fe16c8e9的成熟模式,对 4 个控件统一修复(共 5 个文件):DSpinBox/DDoubleSpinBox(include/widgets/dspinbox.h+src/widgets/dspinbox.cpp)wheelEvent:有焦点 → 调QSpinBox/QDoubleSpinBox::wheelEvent(保留滚轮调值);无焦点 →QWidget::wheelEvent(ignore()传播给 scrollarea)。DComboBox(include/widgets/dcombobox.h+src/widgets/dcombobox.cpp)wheelEvent:有焦点 → 调QComboBox::wheelEvent(保留滚轮切项);无焦点 →QWidget::wheelEvent(传播)。DSlider(src/widgets/dslider.cpp)eventFilter中处理:内部 slider 无焦点时e->ignore()+return true,在 Qt6 下取消 accept 使事件传播给父控件,等价于fe16c8e9模式。行为 / Behavior
readOnlyspinbox 聚焦后滚动:基类自身ignore(),事件正常传播,无需额外判断。DLineEdit/DFileChooserEdit不受影响(QLineEdit不重写wheelEvent,默认ignore()),未改动。#if条件编译。对 Qt5 无影响(本就正常),修复 Qt6 回归。自测 / Test
dspinbox.cpp/dcombobox.cpp/dslider.cpp均编译通过,零 error / warning。examples/collections中 spinbox / combobox / slider 在 scrollarea 内 → 无焦点滚轮滚动页面,有焦点滚轮调值 / 切项。关联 / References
Summary by Sourcery
Adjust wheel event handling for DTK widgets so unfocused controls no longer block parent scroll areas, restoring expected scroll behavior in Qt6.
Bug Fixes: