如何在 Qml 中模拟按键事件?



我正在使用QML实现定制的虚拟键盘。我的目的是模拟当我在虚拟键盘中单击按钮时真实键盘的物理按键信号。我已经按照Qt虚拟键盘中的教程进行操作,并成功构建并运行了示例代码。

问题在于示例代码在 C++ 类中使用QCoreApplication::sendEvent()函数将按键事件发送到重点 QObject。当我在main.qml中导入QtQuick.Controls 1.3作为指南时,它运行良好,但是当我更改为QtQuick.Controls 2.2时不起作用,这在我的应用程序中是必不可少的。下面是示例代码的核心:

void KeyEmitter::emitKey(Qt::Key key)
{
QQuickItem* receiver = qobject_cast<QQuickItem*>(QGuiApplication::focusObject());
if(!receiver) {
return;
}
QKeyEvent pressEvent = QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier, QKeySequence(key).toString());
QKeyEvent releaseEvent = QKeyEvent(QEvent::KeyRelease, key, Qt::NoModifier);
QCoreApplication::sendEvent(receiver, &pressEvent);
QCoreApplication::sendEvent(receiver, &releaseEvent);
}

那么,如何将按键事件发送到我的应用程序呢?

我认为focusObject是实际点击的按钮,因此向该按钮发送QKeyEvent而不是TextField是没有意义的。

如何传递实际接收器对象的指针,而不是向QGuiApplication询问focusObject

试试这个:

Keyemitter.h 文件(仅标头,您不需要 cpp 文件(:

#ifndef KEYEMITTER_H
#define KEYEMITTER_H
#include <QObject>
#include <QCoreApplication>
#include <QKeyEvent>
class KeyEmitter : public QObject
{
Q_OBJECT
public:
KeyEmitter(QObject* parent=nullptr) : QObject(parent) {}
Q_INVOKABLE void keyPressed(QObject* tf, Qt::Key k) {
QKeyEvent keyPressEvent = QKeyEvent(QEvent::Type::KeyPress, k, Qt::NoModifier, QKeySequence(k).toString());
QCoreApplication::sendEvent(tf, &keyPressEvent);
}
};
#endif // KEYEMITTER_H

主.cpp文件:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickView>
#include <QQmlContext>
#include "keyemitter.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQuickView view;
KeyEmitter keyEmitter;
view.rootContext()->setContextProperty("keyEmitter", &keyEmitter);
view.setSource(QStringLiteral("qrc:/main.qml"));
view.show();
return app.exec();
}

主.qml文件:

import QtQuick 2.12
import QtQuick.Controls 2.12
Rectangle {
anchors.fill: parent
color: "red"
Column{
Row {
TextField {
id: tf
Component.onCompleted: { console.log(tf); }
text: "123"
}
}
Row {
Button {
text: "1"
onClicked: keyEmitter.keyPressed(tf, Qt.Key_1)
}
Button {
text: "2"
onClicked: keyEmitter.keyPressed(tf, Qt.Key_2)
}
Button {
text: "3"
onClicked: keyEmitter.keyPressed(tf, Qt.Key_3)
}
}
Row {
Button {
text: "DEL"
onClicked: keyEmitter.keyPressed(tf, Qt.Key_Backspace)
}
Button {
text: "OK"
onClicked: keyEmitter.keyPressed(tf, Qt.Key_Enter)
}
Button {
text: "ESC"
onClicked: keyEmitter.keyPressed(tf, Qt.Key_Escape)
}
}
}
}

谢谢@Ponzifex,

你是对的。当我单击自定义键盘中的按钮时,焦点对象会立即更改为单击的按钮,而不是所需的文本字段。

简单地说,将焦点按钮的策略更改为 NoFocus 可以解决我的问题。

Button {
id: btnOne                
focusPolicy: Qt.NoFocus
text: qsTr("1")
onClicked: {
keyEmitter.emitKey( Qt.Key_1 )
}
}

最新更新