QToolButton按下Alt后显示菜单

时间:2018-08-13 06:57:16

标签: c++ qt

我有一个带有相关菜单的工具按钮。

m_mainMenuButton = new ToolButton("menu.png", tr("Open menu"));
m_mainMenuButton->setMenu(m_mainMenu);
m_mainMenuButton->setPopupMode(QToolButton::InstantPopup);

我希望在用户按下并释放Alt时显示此菜单。这样,普通的QMenuBar就可以在Windows上被激活(我想使用此工具按钮代替QMenuBar)。我尝试过:

m_mainMenuButton->setShortcut(QKeySequence(Qt::Key_Alt));

,但在按下并释放Alt时不显示菜单。或这样:

auto shortcut = new QShortcut(QKeySequence(Qt::Key_Alt), this);
connect(shortcut, &QShortcut::activated, m_mainMenuButton, &QToolButton::showMenu);

它什么也没做。我尝试覆盖按键按下和释放事件,但随后发现它干扰了其他将按键Alt用作修饰符的按键快捷方式,例如“ Alt +左​​键”。

任何想法如何做到这一点?

更新一个最小的示例,该示例显示Alt不能用作快捷方式。

#include <QAction>
#include <QApplication>
#include <QLabel>
#include <QMainWindow>
#include <QMenu>
#include <QShortcut>
#include <QToolButton>
#include <QVBoxLayout>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QMainWindow w;

    auto label = new QLabel();

    auto menu = new QMenu(&w);
    // intentionally added a shortcut which contains Alt as modifier to test it does not interfere with the menu
    menu->addAction("Action", [label]{ label->setText("Trigered!"); }, QKeySequence("Alt+Left"));

    auto btn = new QToolButton();
    btn->setMenu(menu);
    btn->setPopupMode(QToolButton::InstantPopup);

    // the following lines do not have any effect, the menu is not shown when Alt is pressed and released
    auto shortcut = new QShortcut(QKeySequence(Qt::Key_Alt), &w);
    QObject::connect(shortcut, &QShortcut::activated, btn, &QToolButton::showMenu);

    auto container = new QWidget();
    auto layout = new QVBoxLayout(container);
    layout->addWidget(btn);
    layout->addWidget(label);
    w.setCentralWidget(container);
    w.show();

    return a.exec();
}

2 个答案:

答案 0 :(得分:0)

尝试使用QObject :: installEventFilter
(QObject :: eventFilter(obj,event))。

例如

QtStackOverflow.h

#pragma once

#include <QtWidgets/QMainWindow>
#include <QToolButton>
#include "ui_QtStackOverflow.h"

class QtStackOverflow : public QMainWindow
{
    Q_OBJECT

public:
    QtStackOverflow(QWidget *parent = Q_NULLPTR);

private:
    Ui::QtStackOverflowClass ui;
};

class KeyPressEater : public QObject
{
   Q_OBJECT

public:
   KeyPressEater(QToolButton*btn) : keyOtherPush(false), keyAltPush(false) { _btn = btn; }

protected:
   bool eventFilter(QObject *obj, QEvent *event);

private:
   QToolButton * _btn;
   bool keyOtherPush;
   bool keyAltPush;
};

main.cpp

#include "QtStackOverflow.h"
#include <QtWidgets/QApplication>

#include <QObject>
#include <QEvent>
#include <QKeyEvent>
#include <QLabel>
#include <QMainWindow>
#include <QMenu>
#include <QShortcut>
#include <QToolButton>
#include <QVBoxLayout>

int main(int argc, char *argv[])
{
   QApplication a(argc, argv);

   QMainWindow w;

   auto label = new QLabel();

   auto menu = new QMenu(&w);
   // intentionally added a shortcut which contains Alt as modifier to test it does not interfere with the menu
   int number = 0;
   menu->addAction("Action", [label, &number] {
      label->setText(QString("%1 %2 ").arg("Trigered!").arg(number));
      number++;
   }, QKeySequence("Alt+Left"));

   auto btn = new QToolButton();
   btn->setMenu(menu);
   btn->setPopupMode(QToolButton::InstantPopup);

   // the following lines do not have any effect, the menu is not shown when Alt is pressed and released
   auto shortcut = new QShortcut(QKeySequence(Qt::Key_Alt), &w);
   QObject::connect(shortcut, &QShortcut::activated, btn, &QToolButton::showMenu);

   KeyPressEater *m_keyPressEater;
   m_keyPressEater = new KeyPressEater(btn);
   qApp->installEventFilter(m_keyPressEater);

   auto container = new QWidget();
   auto layout = new QVBoxLayout(container);
   layout->addWidget(btn);
   layout->addWidget(label);
   w.setCentralWidget(container);
   w.show();

   return a.exec();
}

bool KeyPressEater::eventFilter(QObject *obj, QEvent *event)
{
   if (event->type() == QEvent::KeyPress)
   {
      int key = static_cast<QKeyEvent *>(event)->key();

      if (key == Qt::Key_Alt)
      {
         keyAltPush = true;
      }
      else {
         keyOtherPush = true;
      }

      return QObject::eventFilter(obj, event);
   }
   else if (event->type() == QEvent::KeyRelease)
   {
      int key = static_cast<QKeyEvent *>(event)->key();

      if (key == Qt::Key_Alt) {
         if (keyAltPush == true && keyOtherPush == false) {
            _btn->showMenu();
         }
      }
      else {
         keyAltPush = false;
         keyOtherPush = false;
      }
      return true;
   }
   else {
      return QObject::eventFilter(obj, event);
   }
}

在这种情况下,您可以随时获得所有按键。

然后您需要检查QObject * senderObj = sender()

答案 1 :(得分:0)

这是受QMenuBar中的Qt实现启发的版本:

[A > b for b in B]

[array([ True, False,  True,  True], dtype=bool),
 array([False, False, False,  True], dtype=bool)]

Alt-Left快捷键可以正常工作,并且按钮菜单由Alt-Pres-Release切换。