gpt4 book ai didi

c++ - QML ListView和按键导航——单键事件的处理

转载 作者:行者123 更新时间:2023-11-30 03:34:39 24 4
gpt4 key购买 nike

我使用的是 Qt 5.6.2 (Windows 10) 并且有一个 QObject 派生的映射器,它将 QKeyEvent 发送到当前聚焦的 QML 项目。我的基类有一个虚拟 mapToKey() 函数,然后在我想使用的各种映射器中覆盖它。例如,下面的映射函数是我的 LeftArrowMapper 的一部分,并发送左箭头键事件:

void LeftArrowMapper::mapToKey()
{
// Retrieve root of QML context
QObject* root = engine->rootObjects()[0];
// Get currently focused item
QQuickItem *item = (root->property("activeFocusItem")).value<QQuickItem *>();
if (item == NULL) qDebug() << "No item";

// Create a key and a key event
Qt::Key key = Qt::Key_Left;
QKeyEvent* event = new QKeyEvent(QKeyEvent::KeyPress,
key,
Qt::NoModifier,
KeySequence(key).toString());

// Send it to the focused QML item
QCoreApplication::postEvent(item,event);
}

如果给定的项目支持按键事件,它将做出相应的 react 。否则接收到的按键事件不会触发任何响应。我已经使用 TextField 对其进行了测试,这是一个基于 Text 的自定义组件(它只是使用通过键事件发送的文本更新 text 属性) 等等,我没有遇到任何问题。直到我开始使用 ListView...

我正在尝试使用键盘的左右箭头键在 ListView 中导航,其中键事件是使用我的映射器的 mapToKey() 函数人工创建的(这里的要点:映射硬件事件,如按下真实按钮到 Qt 事件)。在 Qt 5.6 中,将 focus 属性设置为 true 可以使用键进行导航(在 5.8 中,可能还有 5.7 中,keyNavigationEnabled 属性必须设置为true;Qt 5.6 中没有这样的属性。

我的 ListView 如下所示:

ListView {
id: list
orientation: Qt.Horizontal
width: rootWindow.width
height: 50

Keys.onPressed: {
console.log("list: " + event.key + " : " + event.text)
if (event.key == Qt.Key_Left) console.log("Moving to the left");
else if (event.key == Qt.Key_Right) console.log("Moving to the right");
}

model: ListModel {
id: items
}
delegate: Rectangle {
width: 50
height: 50
Text {
anchors.centerIn: parent
text: "[" + name + "]"
}
}

Component.onCompleted: function() {
for(var i = 1; i <= 100; i++) {
items.append({"name" : i});
}
}
onFocusChanged: {
console.log("List focus has changed");
}
}

我发现的问题是这个 QML 组件处理关键事件的方式很奇怪。它似乎试图模仿基于动力学的滑动(考虑到加速度),您可以在滚动其中的项目时使用鼠标进行滑动。这意味着:

  • 如果长时间按住箭头键(大约 2 秒),则会触发 ScrollView - 一旦启用,它不会滚动单个项目,而是滚动多个
  • 触发上述滚动后,用户可以继续按方向键继续快速滚动。在这一点上,每个键事件滚动单个项目也是可能的,但是......
  • 改变方向会导致上述行为的重置,因此用户需要执行另一个“触发滚动”事件才能向相反方向滚动
  • 触发多个单独的键事件也会触发滚动,但这次是一次触发一个项目。另外我上面提到的时间间隔似乎并不适用于此。用户需要按给定的箭头键 7 次(至少这是我数过的次数),然后他才能选择列表中的下一个/上一个项目

似乎在内部映射需要一定数量的press-and-releasepress-and-hold-for-X-seconds 按键事件才能真正触发ListView 中的一些响应。

现在我的一位同事创建了我们正在使用的 ListView 的自定义键导航,并且工作正常。但是我想知道是否有一些 secret 设置(或者我们都错过了文档中的备忘录)来处理这个问题。我可以看到这种与键交互的应用(即模拟加速),但对于我正在处理的场景,我真的不需要它,或者至少现在不需要。另外,如果我想在某个时候添加伪加速部分,那么了解事情是如何完成的将非常有用。

最佳答案

当您按下左/右箭头键时,ListView 中基于动力学的滑动是来自 ListView.highlight 的动画.为了使其可见,我们可以将一些代码添加到您的列表中:

ListView {
id: list

Keys.onPressed: {
console.log(list.currentIndex);
//...
}
delegate: Item { // so we can see highlight in background
width: 50
height: 50
Text {
anchors.centerIn: parent
text: "[" + name + "]"
}
}
highlight: Rectangle {
width: 50
height: 50
color: "pink"
}
//...
}

当您按向右箭头键时,currentIndex 会更改,并且突出显示会移动到该索引。如果像这样显式更改 currentIndex,您可以看到相同的动画:

Button {
text: "go to 45"
onClicked: list.currentIndex = 45;
}

要自定义动画,可以改变ListView.highlightMoveDurationListView.highlightMoveVelocity属性,或者设置ListView.highlightFollowsCurrentItem为false来开启它关了。也可以关注ListView example code制作您自己的高亮动画。

It seems that internally the mapping requires a certain amount of press-and-release or press-and-hold-for-X-seconds key events to actually trigger some response in the ListView.

ListView在处理按键事件时并没有魔法,它只是不断地改变currentIndex,而QML中的动画可以完美处理。

关于c++ - QML ListView和按键导航——单键事件的处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41897473/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com