c++ - QToolButton 在按下 Alt 后显示菜单
问题描述
我有一个带有相关菜单的工具按钮。
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+Left”。
任何想法如何做到这一点?
更新一个最小的例子,它表明 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();
}
解决方案
尝试使用 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;
};
主文件
#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()
推荐阅读
- php - PHPMailer 不会通过 localhost 发送电子邮件
- azure-functions - 沙盒 Blazor WebAssemblies 代替 AppDomain 沙盒
- python - 尝试使用 FastAPI 和 python-docx 库读取 docx 文件:AttributeError: 'bytes' object has no attribute 'seek' 错误
- python - Tkinter 回调中的异常:TypeError:float() 参数必须是字符串或数字,而不是“事件”
- c - Linux内核驱动程序挂钩系统调用不起作用
- java - 正则表达式在 Java 中拆分数学运算符
- ios - 从 SwiftUI 中的 fileImporter 修饰符更新进度值
- json - 为什么我的 class.fromJson 方法不起作用?
- python - Airflow PostgresToGCSOperator - 以 EPOCH 格式导出时间戳列
- android - 颤振 | 流式传输的 http.client.send 突然没有收到任何响应