【问题标题】:Assigning Keyboard Shortcuts to QML Components将键盘快捷键分配给 QML 组件
【发布时间】:2012-08-24 22:33:06
【问题描述】:

我正在深入使用 QML 和 Qt Creator 构建桌面应用程序,我目前正在研究键盘处理以及它如何与 QML 元素一起使用。我已经意识到桌面小部件缺乏适当的 QML 替代品。

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

谁能建议在这种情况下该怎么做? Qt 5 有没有这样的功能?我在 Internet 上找不到任何关于此的信息。

【问题讨论】:

  • QShortCut 与基于 QWidget 的类一起使用。没有直接的方法可以让原生 QML 元素响应全局快捷方式。例如,可以为 QML 按钮分配一个键,但它仅在按钮具有焦点时才有效。
  • Application Wide Shortcuts using QShortcut in QML 在同一行中很有趣。我在主 GUI 屏幕上使用 QDeclarativeView(基于 QWidget),其中嵌入了 QML,因此应用程序范围的快捷方式现在很容易。

标签: qt qml qt-quick qt4.7 qt5.1


【解决方案1】:

因此,假设您正在像这样在该按钮单击事件上调用函数,

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

然后您可以通过这种方式分配分配全局键盘快捷键。但限制是全局 QML 元素(包含所有其他 QML 元素的父元素)应该具有焦点。前任。 :

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

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

【讨论】:

    【解决方案2】:

    回答我自己的问题,因为快捷方式现在可以在 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 example

    【讨论】:

      【解决方案3】:

      你可以通过在 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&lt;Shortcut&gt;("Project", 0, 1, "Shortcut");

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

      【讨论】:

        【解决方案4】:

        从 Qt 5.9 开始,所需的行为甚至是 included:

        import QtQuick 2.9
        
        Item {
            Shortcut {
               context: Qt.ApplicationShortcut
               sequences: [StandardKey.Close, "Ctrl+W"]
        
                onActivated: {
                    container.clicked()
                    console.log("JS: Shortcut activated.")
                }
            }
        }
        

        如果您省略上下文,它将仅适用于当前活动的窗口,否则对于整个应用程序,请参阅documentation

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-02
          • 2016-06-22
          • 2012-05-05
          • 1970-01-01
          • 1970-01-01
          • 2012-04-06
          相关资源
          最近更新 更多