我正在实现狭窄的调整手柄,这给了我恼人的行为。当鼠标直接在手柄上时,光标形状与预期一致,但是一旦开始拖动手柄,光标形状就会变得不一致。这有两个原因:
-
当光标快速移动并在手柄前面移动直到手柄"赶上"时(或者当"流体qml"太流体时)-当光标形状快速变化并闪烁时,
这尤其令人讨厌 当光标移动到句柄允许的自由度之外时
我查阅了文档,但它似乎没有包含任何关于锁定光标的内容,直到按下按钮。
我确实设法找到了一个hack来修复它-使用假覆盖MouseArea
与acceptedButtons: Qt.NoButton
-这实际上有助于伪造光标一致性,但有一个自己的问题。有了这个覆盖的鼠标区域,光标在手柄上方时不允许改变为可调整大小的形状,因为手柄在覆盖的鼠标区域下方,所以它根本无法修改光标形状。因此,只有在点击手柄后,调整大小形状才会生效,这远非理想状态。将鼠标覆盖区域设置为enabled: false
不会改变这一点-它仍然会阻止光标形状从底层鼠标区域变化。也有一种解决方法,例如将覆盖的鼠标区域大小设置为0x0,但它有点难看。
理想情况下,光标形状应该一直保持到鼠标区域被按下,不管它是在它的区域内还是在它的区域外——毕竟,如果你走到它的区域外,按下的按钮不会被释放,因此鼠标区域仍然在控制中,应该保持它的光标形状。例如,窗口调整手柄保持调整形状,即使它被移动到调整窗口的大小小于其最小大小,直到按下。
对我来说,MouseArea
的实现似乎存在缺陷-光标形状在按下时不保持,即使禁用鼠标区域也会改变光标形状。
我没有找到一种开箱即用的方法,但是为此创建一个帮助器非常容易。在qml端,你可以使用:
CursorChanger {
cursor: Qt.SizeHorCursor
active: dragArea.containsMouse || dragArea.drag.active
}
在c++端,你需要一个像这样的helper类:
class CursorChanger : public QObject
{
Q_OBJECT
Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
Q_PROPERTY(int cursor READ cursor WRITE setCursor NOTIFY cursorChanged)
// ...
}
在实现中,您可以使用QGuiApplication::setOverrideCursor
和QGuiApplication::restoreOverrideCursor
来实际设置/重置光标。不要忘记在CursorChanger
析构函数中进行重置,如果此时处于活动状态。如果然后注册类型:
qmlRegisterType<CursorChanger>(uri, 1, 0, "CursorChanger");`
我认为当前的行为有一些用例。例如,光标可以传达当前悬停的对象与按下鼠标的对象之间的某种关系。另一个例子,拖拽可以有意地限制其速度,当用户拖得太快时,就会产生取决于后面物品的后果。
dtech的需求肯定更普遍,我也希望将其视为可选功能,而不是作为更改。它现在的方式是为应用程序提供更多功能的组件。我不喜欢修饰过的组件,它们只能完全按照库作者的设想来使用。
对于持久拖动光标,另一个仅使用QML的解决方案是在所有项目后面都有一个MouseArea,以便在需要时保持持久的形状:
Item
{
id: scene; width: 800; height: 600
MouseArea
{
id: mouse
anchors.fill: scene
}
Rectangle
{
id: draggable; width: 40; height: 30; color: "red"
MouseArea
{
anchors.fill: draggable
drag.target : draggable
//set and unset a persistent cursor
onPressed : mouse.cursorShape = Qt.DragMoveCursor;
onReleased: mouse.cursorShape = Qt.ArrowCursor; //QT default cursor
//let non default scene cursors prevail over the item's
cursorShape: mouse.cursorShape === Qt.ArrowCursor ?
Qt.OpenHandCursor : mouse.cursorShape;
}
}
}