我正在使用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);
}
如果给定项目支持关键事件,它将作出相应的反应。否则,收到的键事件不会触发任何响应。我已使用TextField
(一个基于自定义Text
的组件(仅使用通过键事件发送的文本更新text
属性)等对其进行了测试。我还没有&# 39;遇到任何问题。直到我开始使用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组件处理关键事件的奇怪方式。似乎它试图模仿基于动力学的滑动(加速度被考虑),当您滚动浏览其中的项目时,您可以使用鼠标。这意味着以下内容:
在内部,映射似乎需要一定量的按下并释放或按住-X-seconds 键事件才能实际触发ListView
中的一些回复。
现在我的一位同事创建了我们正在使用的ListView
的自定义键导航,它运行正常。但是,我想知道是否有一些秘密设置(或者我们都错过了文档中的备忘录)来处理这个问题。我可以看到这种类型的互动应用(即模拟加速),但对于我正在努力的场景,我真的不需要它,或者至少现在不需要它。另外,如果我想在某些时候添加伪加速部分,知道如何完成这将是非常有用的。
答案 0 :(得分:2)
按左/右箭头键时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.highlightMoveDuration
和ListView.highlightMoveVelocity
属性,或将ListView.highlightFollowsCurrentItem
设置为false以将其关闭。您也可以按照ListView
example code制作自己的高光动画。
在内部,映射似乎需要一定量的按下并释放或按住X秒键事件才能在
ListView
中实际触发某些响应。
ListView
处理关键事件时没有任何魔力,它只是经常更改currentIndex
,而QML中的动画可以完美地处理它。