QKeyEvent nativeVirtualKey là không xác định
Tôi cần mã khóa gốc của khóa trong ứng dụng QML của mình. Tôi có trình xử lý khóa sau trong một mục QML.
Keys.onPressed: {
console.log("Key: ", event.key)
console.log("Native: ", event.nativeVirtualKey);
event.accepted = true
}
Các event.keyhoạt động tốt khi nhấn các phím, nhưng event.nativeVirtualKeykhông xác định được. ví dụ.
qml: Key: 70
qml: Native: undefined
Có gì đó sai với mã của tôi? Làm cách nào để tải nativeVirtualKey?
Tôi hiện thấy trong tài liệu rằng "Lưu ý: Khóa ảo gốc có thể bằng 0, ngay cả khi sự kiện khóa chứa thông tin mở rộng." https://doc.qt.io/qt-5/qkeyevent.html#nativeVirtualKey Thật không may, không có đề cập đến khi nào hoặc điều kiện nào khiến khóa gốc ảo biến mất.
Trả lời
Như tôi đã chỉ ra trong câu trả lời này : KeyEventkhông phải là một QKeyEventmà là một QObject hiển thị một số thuộc tính nhưng không phải tất cả. Cách giải quyết là tạo QObject cài đặt bộ lọc sự kiện cho mục và hiển thị thuộc tính đó:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickItem>
class KeyHelper: public QObject{
Q_OBJECT
Q_PROPERTY(QQuickItem* target READ target WRITE setTarget NOTIFY targetChanged)
public:
using QObject::QObject;
QQuickItem* target() const {
return m_target;
}
void setTarget(QQuickItem* item){
if(m_target)
m_target->removeEventFilter(this);
m_target = item;
if(m_target)
m_target->installEventFilter(this);
Q_EMIT targetChanged(m_target);
}
bool eventFilter(QObject *watched, QEvent *event){
if(watched == m_target && event->type() == QEvent::KeyPress){
if(QKeyEvent *ke = static_cast<QKeyEvent *>(event))
Q_EMIT nativeVirtualKeyChanged(ke->nativeVirtualKey());
}
return QObject::eventFilter(watched, event);
}
signals:
void nativeVirtualKeyChanged(quint32 nativeVirtualKey);
void targetChanged(QQuickItem* item);
private:
QPointer<QQuickItem> m_target;
};
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
qmlRegisterType<KeyHelper>("qt.keyhelper", 1, 0, "KeyHelper");
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
#include "main.moc"
import QtQuick 2.12
import QtQuick.Window 2.12
import qt.keyhelper 1.0
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Item {
id: item
focus: true
anchors.fill: parent
}
KeyHelper{
target: item
onNativeVirtualKeyChanged: console.log(nativeVirtualKey)
}
}
Đây là một điều chỉnh nhỏ về câu trả lời của @ eyllanesc thay thế eventFilterđể đóng gói lại QEvent dưới dạng QVariantMap để nó có thể được gọi trực tiếp với các hàm mong đợi KeyEventAPI.
class KeyHelper: public QObject{
... // same as @ellyanesc's answer
bool eventFilter(QObject *watched, QEvent *event){
if(watched == m_target && event->type() == QEvent::KeyPress){
if(QKeyEvent *ke = static_cast<QKeyEvent *>(event)) {
// it seems we cannot send the event in a signal since it doesnt inherit from QObject.
// copy the relevant values to an event object
QVariantMap eventObject;
eventObject["key"] = ke->key();
eventObject["modifiers"] = int(ke->modifiers());
eventObject["nativeVirtualKey"] = ke->nativeVirtualKey();
eventObject["nativeModifiers"] = ke->nativeModifiers();
Q_EMIT nativeKeyPress(eventObject);
}
}
return QObject::eventFilter(watched, event);
}
signals:
void nativeKeyPress(QVariantMap event);
... // same as @ellyanesc's answer
};
Và sau đó trong tệp qml
KeyHelper{
target: ...
onNativeKeyPress: {
console.log("native key press ", JSON.stringify(event))
}
}