Qt QML ComboBox覆盖滚轮事件

3

有没有办法覆盖ComboBox的MouseArea以忽略滚轮事件而不是更改当前索引? ComboBox本身没有选项可以更改滚轮焦点行为。 到目前为止,我尝试使用以下代码覆盖CB MouseArea中的onWheel:

ComboBox {
  Component.onCompleted: {
    for (var i = 0; i < combobox_ctrl.children.length; ++i) {
      console.log(combobox_ctrl.children[i])
      console.log(combobox_ctrl.children[i].hasOwnProperty('onWheel'))

      if (combobox_ctrl.children[i].hasOwnProperty('onWheel')) {
        console.log(combobox_ctrl.children[i]['onWheel'])
        combobox_ctrl.children[i]['onWheel'] = function() { console.log("CB on wheel!") }
        //combobox_ctrl.children[i]onWheel = function() { console.log("CB on wheel!") 
        //combobox_ctrl.children[i].destroy()
      }
    }
  }
}

但是我遇到了

类型错误:无法分配给只读属性“wheel”

有人能够在Qml中禁用ComboBox上的滚轮事件吗?

// 编辑

例如,在Slider控件中,我可以像这样删除滚轮事件处理:

Slider {
  Component.onCompleted: {
    for (var i = 0; i < slider.children.length; ++i) {
      console.log(slider.children[i])
      if (slider.children[i].hasOwnProperty("onVerticalWheelMoved") && slider.children[i].hasOwnProperty("onHorizontalWheelMoved")) {
        console.log("Found wheel area!")
        slider.children[i].destroy()
      }
    }
  }
}

但是在滑块中,WheelArea不负责处理“click”事件。

5个回答

4
你可以将 MouseArea 放置在 ComboBox 上并捕获滚轮事件。
ComboBox {
    anchors.centerIn: parent
    model: [ "Banana", "Apple", "Coconut" ]
    MouseArea {
        anchors.fill: parent
        onWheel: {
            // do nothing
        }
        onPressed: {
            // propogate to ComboBox
            mouse.accepted = false;
        }
        onReleased: {
            // propogate to ComboBox
            mouse.accepted = false;
        }
    }
}

是的,但它会处理事件,所以例如combobox所在的ScrollArea不会收到该事件。 - Kamil Klimek

2

目前不可能实现,因为ComboBox不是从MouseArea派生的,而是从FocusScope派生的,后者不支持这些事件。

最近在建议中提到了类似的问题:

禁用QtQuick.Controls上的鼠标滚轮滚动事件


如果你想要一个hacky的方法,似乎你唯一剩下的选择就是对ComboBox.qml应用一个修补程序,删除onWheel处理程序:

diff --git a/src/controls/ComboBox.qml b/src/controls/ComboBox.qml
index 4e29dfe..3413cac 100644
--- a/src/controls/ComboBox.qml
+++ b/src/controls/ComboBox.qml
@@ -407,13 +407,6 @@ Control {
                 popup.toggleShow()
             overridePressed = false
         }
-        onWheel: {
-            if (wheel.angleDelta.y > 0) {
-                __selectPrevItem();
-            } else if (wheel.angleDelta.y < 0){
-                __selectNextItem();
-            }
-        }
     }

另一种不需要修改Qt代码的替代方法是在ComboBox上方添加一个中间的MouseArea,并且只将特定事件转发到ComboBox的MouseArea。或者,创建一个自定义的C++项来实现相同的功能,这样你可以更好地控制。

我知道直接通过参数是不可能的。我正在寻找一些替代的“hacky”方法,比如使用滑块。 - Kamil Klimek

1

好的。经过一番探索,我已经想出了一种对我来说可接受的解决方案,但在某些情况下可能会引入一些退步。pressed和hovered属性不再可用。

import QtQuick.Controls.Private 1.0

ComboBox {
  Component.onCompleted: {
    for (var i = 0; i < combobox_ctrl.children.length; ++i) {
      if (combobox_ctrl.children[i].hasOwnProperty('onWheel') && combobox_ctrl.children[i] !== mouseArea) {
        combobox_ctrl.children[i].destroy()
      }
    }
  }

  MouseArea {
    id: mouseArea
    anchors.fill: parent

    onPressed: {
      if (combobox_ctrl.activeFocusOnPress)
        forceActiveFocus()
      if (!Settings.hasTouchScreen)
        combobox_ctrl.__popup.toggleShow()
    }

    onClicked: {
      if (Settings.hasTouchScreen)
        combobox_ctrl.__popup.toggleShow()
    }
  }
}

这样,我们就可以模拟最初在ComboBox内部的鼠标区域。弹出窗口的显示方式保持不变(至少我还没有发现任何退化)。然而,目前有两个属性是无法访问的。

非常感谢!我很喜欢这个解决方案,直到 https://bugreports.qt.io/browse/QTBUG-48620 得到修复。我将把它放在一个单独的控件中,以便它是可重用的。 - Boy

1
我创建了一个名为NonScrollingComboBox.qml的单独文件,其中包含以下代码,遵循此帖子:https://dev59.com/z4_ea4cB1Zd3GeqPVv_m#33080217 现在,在我不想要鼠标滚动更改值的地方,我只需将NonScrollingComboBox用作组件,而不是ComboBox
import QtQuick 2.0
import QtQuick.Controls 1.4

ComboBox {
    id: combobox_ctrl
    Component.onCompleted: {
        for (var i = 0; i < combobox_ctrl.children.length; ++i) {
            if (combobox_ctrl.children[i].hasOwnProperty('onWheel')
                    && combobox_ctrl.children[i] !== mouseArea) {
                combobox_ctrl.children[i].destroy()
            }
        }
    }
    MouseArea {
        id: mouseArea
        anchors.fill: parent

        onPressed: {
            if (combobox_ctrl.activeFocusOnPress)
                forceActiveFocus()
            combobox_ctrl.__popup.toggleShow()
        }

        onClicked: {
            combobox_ctrl.__popup.toggleShow()
        }
    }
}

使用方法:

NonScrollingComboBox {
    anchors.verticalCenter: parent.verticalCenter
    model: ["item one", "item 2"]
}

0

这似乎仅适用于Qt Quick Controls 1 ComboBox。在Qt Quick Controls 2 ComboBox上,默认情况下未启用滚轮鼠标事件,可以通过设置属性wheelEnabled(在基类Control中记录)手动启用。此外,组合框不会在鼠标事件上保持“焦点”,因此您可以自由地在其他鼠标区域上使用滚轮,只需进入它们即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接