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

时间:2020-05-27 15:44:03

标签: c++ qt qml signals-slots qtvirtualkeyboard

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

问题是示例代码在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);
}

那么如何将按键事件发送到我的应用程序?任何帮助将不胜感激。

谢谢

2 个答案:

答案 0 :(得分:1)

我认为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

main.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();
}

main.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)
            }
        }
    }
}

答案 1 :(得分:0)

感谢@Ponzifex,

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

将按钮的focusPolicy更改为NoFocus即可解决我的问题。

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