1

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

问题是示例代码使用QCoreApplication::sendEvent()C++ 类中的函数将按键事件发送到焦点 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);
}

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

4

2 回答 2

2

我认为 thefocusObject是实际点击的按钮,所以发送一个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)
            }
        }
    }
}

于 2020-05-28T16:48:40.223 回答
1

感谢@Ponzifex,

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

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

Button {
    id: btnOne                
    focusPolicy: Qt.NoFocus
    text: qsTr("1")
    onClicked: {
        keyEmitter.emitKey( Qt.Key_1 )
    }
}
于 2020-09-05T03:04:51.660 回答