如何在Qt中检测全局按键序列的按下?

13

我想检测按键序列是否被按下并在该事件上执行某些任务,涉及到it技术和Qt。目前我可以检测特定小部件的按键按下,但如何检测全局按键按下呢?所谓全局,即使应用程序被最小化或隐藏,它也应该检测到按键按下。

我尝试为应用程序创建一个eventFilter,首先重载QObject::eventFilter,像这样:

bool GlobalEventFilter::eventFilter(QObject *Object, QEvent *Event)
{
  if (Event->type() == QEvent::KeyPress)
  {
    QKeyEvent *KeyEvent = (QKeyEvent*)Event;

    switch(KeyEvent->key())
    {
      case Qt::Key_F1:
        cout<<"F1 press detected"<<endl;
        return true;
      default:
        break;
    }
  }
  return QObject::eventFilter(Object,Event);
}

然后将该对象安装为我的应用程序的eventFilter:

QApplication a(argc,argv);
a.installEventFilter(new GlobalEventFilter());

我还尝试了这样做:

QCoreApplication::instance()->installEventFilter(new GlobalEventFilter());

在两种情况下,当我的应用窗口打开时,我能够检测到按键,但是当窗口被最小化或隐藏时,则无法检测到。如何解决这个问题?

这个问题和答案的质量比链接中的那个要好得多。我投票重新开放。 - Adrian Maire
2
@Adrian 我同意。我重新打开了这个问题,并将另一个问题标记为重复。 - Adrian Mole
2个回答

6

请参阅QKeyEvent文档

按键事件在按下或释放按键时发送到具有键盘输入焦点的窗口小部件。

这意味着,如果您希望使用QKeyEvent,您需要拥有键盘焦点。过滤这些事件在概念上也不会改变它。我不确定您从哪里得到了过滤想法。

您可能需要考虑替代解决方案,例如在kwin中的实现方式等。总的来说,对于这种用例要小心。它可能会产生奇怪的效果而用户却没有注意到。

您可以查看此类:

QxtGlobalShortcut类参考

然后您可以编写以下内容:

main.cpp

#include <QxtGlobalShortcut>

#include <QApplication>
#include <QMainWindow>
#include <QDebug>

class MyGlobalShortcutHandler : public QObject
{
    Q_OBJECT
public:
    explicit MyGlobalShortcutHandler(QObject *parent = 0)
        : QObject(parent)
    {
        m_globalShortcut.setShortcut(QKeySequence("Ctrl+Shift+X"));
        m_globalShortcut.setEnabled(true);

        connect(&m_globalShortcut, SIGNAL(activated()), SLOT(handleGlobalShortcut()));
    }

public slots:
    void handleGlobalShortcut()
    {
        qDebug() << "Global shortcut handled";
    }

private:
    QxtGlobalShortcut m_globalShortcut;
};

#include "main.moc"

int main(int argc, char **argv)
{
    QApplication application(argc, argv);
    QMainWindow mainWindow;
    MyGlobalShortcutHandler myGlobalShortcut();
    mainWindow.show();
    return application.exec();
}

main.pro

TEMPLATE = app
TARGET = main
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += qxt
QXT = core gui
SOURCES += main.cpp

构建和运行

qmake-qt4 && make && ./main

这段代码应该可以在至少Qt 4上运行。它对我来说打印出了调试语句。您可以轻松地在您的端上验证这一点。

要获取libqxt库,请访问以下链接:

http://dev.libqxt.org/libqxt/wiki/Home


我见过很多应用程序都这样做。这并不是很难的任务。事实上,我以前使用WinApi已经完成了它。 - user221458
我不在乎它是QKeyEvent还是其他什么。如果可能的话,我只想要一种Qt的方法来实现它。如果不行,我就得使用WinApi来实现。 - user221458
我无法下载Qxt库。我一直收到这个错误:超过了此资源的速率限制。 - user221458
@user221458:尝试使用http://dev.libqxt.org/libqxt/get/v0.6.2.tar.gz,并使用Total Commander插件或类似工具进行解压缩。如果您无法完成此操作,我可以为您重新打包。 - László Papp
1
LGPL是Qt的商业版本,因为它可以在商业应用程序中很好地使用... - László Papp
显示剩余3条评论

6
这个功能在Qt中没有被实现。您可以使用Qxt,它是Qt的扩展库,提供了一组跨平台的实用工具类,以添加Qt中不容易获得的功能。其中包括全局快捷键(热键),即使应用程序最小化也能检测按键按下。
编译和链接应用程序到Qxt之后,您可以包含QxtGlobalShortcut:
#include <QxtGlobalShortcut>

示例用法:

QxtGlobalShortcut* shortcut = new QxtGlobalShortcut(window);
connect(shortcut, SIGNAL(activated()), window, SLOT(toggleVisibility()));
shortcut->setShortcut(QKeySequence("Ctrl+Shift+F12"));

看起来很有前途,但我不想为了实现它而在我的项目中添加额外的库。 - user221458
我无法从他们的网站下载Qxt: 当我尝试打开此链接http://dev.libqxt.org/libqxt/get/v0.6.2.zip时,我收到以下错误消息:该资源的速率限制已超过是否有其他镜像站点? - user221458
有时我会遇到同样的错误,而有时候却不会。尝试刷新下载链接,也许你可以得到它。 - Nejat
谢谢您的回答。我知道这个问题已经很久了,但是可以问一下,如果我想让鼠标点击,我应该写什么?提前感谢。 - user7179690

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