给QML组件分配键盘快捷键

17

我正在使用QML和Qt Creator构建桌面应用程序,并正在研究键盘处理及其与QML元素的配合方式。我已经意识到Desktop Widgets在QML中缺乏适当的替代品。

我目前的问题是,我希望为某些特定的QML组件分配一些全局键盘快捷键(例如将键盘快捷键分配给GUI上的按钮),以激活它们。我能做到的最好的事情是使用FocusScopes和Key Navigation来通过键盘导航GUI,但这并不是同一回事。

有人可以建议在这种情况下该怎么办吗?Qt 5中是否会提供此类功能?我在互联网上找不到任何关于此的信息。


尝试使用这个QShortcut:http://doc.qt.nokia.com/4.7-snapshot/qshortcut.html - RajaRaviVarma
1
QShortCut适用于基于QWidget的类。没有直接的方法使本地QML元素响应全局快捷键。例如,可以为QML按钮分配一个键,但仅当该按钮具有焦点时才起作用。 - Vikas Bhargava
2
使用QML中的QShortcut实现应用程序范围内的快捷键是一件有趣的事情。我正在使用一个基于QWidget的QDeclarativeView作为主GUI屏幕,并在其中嵌入了QML,因此现在很容易实现应用程序范围内的快捷键。 - Vikas Bhargava
4个回答

13

自问自答:现在可以在Qt 5.1.1中实现快捷方式了。 使用QML Action项,可以轻松将快捷键绑定到QtQuick控件,如ButtonToolButtonsMenuItem。例如:

ApplicationWindow {
    ...
    ToolButton { action: openAction } // Add a tool button in a ToolBar
    ...
    Action {
        id: openAction
        text: "&Open"
        shortcut: "Ctrl+O"
        onTriggered: // Do some action
        tooltip: "Open an image"
    }
}

按下Ctrl+O将执行onTriggered部分指定的操作。

请参阅Qt Quick Controls Gallery示例


新链接:https://doc.qt.io/qt-5/qtquickcontrols-gallery-example.html(我无法编辑答案) - undefined

5

您可以通过在C++(Qt)中使用EventFilter来完全在QML中使用快捷方式。

以下是实现步骤:

1. Create a Shortcut class by C++.
2. Register QML Type for Shortcut class
3. Import Shortcut to QML file and handle it.

#ifndef SHORTCUT_H
#define SHORTCUT_H

#include <QDeclarativeItem>

class Shortcut : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QVariant key READ key WRITE setKey NOTIFY keyChanged)
public:
    explicit Shortcut(QObject *parent = 0);

    void setKey(QVariant key);
    QVariant key() { return m_keySequence; }

    bool eventFilter(QObject *obj, QEvent *e);

signals:
    void keyChanged();
    void activated();
    void pressedAndHold();

public slots:

private:
    QKeySequence m_keySequence;
    bool m_keypressAlreadySend;
};

#endif // SHORTCUT_H

#include "shortcut.h"
#include <QKeyEvent>
#include <QCoreApplication>
#include <QDebug>
#include <QLineEdit>
#include <QGraphicsScene>

Shortcut::Shortcut(QObject *parent)
    : QObject(parent)
    , m_keySequence()
    , m_keypressAlreadySend(false)
{
    qApp->installEventFilter(this);
}

void Shortcut::setKey(QVariant key)
{
    QKeySequence newKey = key.value<QKeySequence>();
    if(m_keySequence != newKey) {
        m_keySequence = key.value<QKeySequence>();
        emit keyChanged();
    }
}

bool Shortcut::eventFilter(QObject *obj, QEvent *e)
{
    if(e->type() == QEvent::KeyPress && !m_keySequence.isEmpty()) {
//If you want some Key event was not filtered, add conditions to here
        if ((dynamic_cast<QGraphicsScene*>(obj)) || (obj->objectName() == "blockShortcut") || (dynamic_cast<QLineEdit*>(obj)) ){
            return QObject::eventFilter(obj, e);
        }
        QKeyEvent *keyEvent = static_cast<QKeyEvent*>(e);

        // Just mod keys is not enough for a shortcut, block them just by returning.
        if (keyEvent->key() >= Qt::Key_Shift && keyEvent->key() <= Qt::Key_Alt) {
            return QObject::eventFilter(obj, e);
        }

        int keyInt = keyEvent->modifiers() + keyEvent->key();

        if(!m_keypressAlreadySend && QKeySequence(keyInt) == m_keySequence) {
            m_keypressAlreadySend = true;
            emit activated();
        }
    }
    else if(e->type() == QEvent::KeyRelease) {
        m_keypressAlreadySend = false;
    }
    return QObject::eventFilter(obj, e);
}

qmlRegisterType<Shortcut>("Project", 0, 1, "Shortcut");

import Project 0.1

Rectangle {
.................
.................
Shortcut {
        key: "Ctrl+C"
        onActivated: {
            container.clicked()
            console.log("JS: " + key + " pressed.")
        }
    }

}


5
从Qt 5.9开始,所期望的行为甚至已经被包含在内:
import QtQuick 2.9

Item {
    Shortcut {
       context: Qt.ApplicationShortcut
       sequences: [StandardKey.Close, "Ctrl+W"]

        onActivated: {
            container.clicked()
            console.log("JS: Shortcut activated.")
        }
    }
}

如果省略上下文,则该快捷键只适用于当前活动窗口,否则适用于整个应用程序,请参阅文档

0

假设您在按钮点击事件中调用了一个函数,就像这样:

Button {
  ...
  MouseArea {
    anchor.fill: parent
    onClicked: callThisFunction();
  }
}

然后你可以通过以下方式分配全局键盘快捷键。但是限制是全局 QML 元素(一个包含所有其他 QML 元素的父元素)应该具有焦点。例如:

Rectangle {
  id: parentWindow
  ...
  ...
  Button {
    ...
    MouseArea {
      anchor.fill: parent
      onClicked: callThisFunction();
    }
  }
  Keys.onSelectPressed: callThisFunction()
}

这不完全是你想要的,但它可能会有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接