我有一个Qt应用程序,在Qt Designer表单操作中定义了几个窗口快捷方式。快捷方式很有效,直到它们被按下,同时焦点位于处理相同组合的小部件上(覆盖我的窗口快捷方式)。
我希望有相反的行为:窗口快捷方式覆盖重点小部件快捷方式。
我尝试使用eventFilter
并且我可以捕获所需的事件,但我无法以调用全局快捷方式的方式重新发送它们。我可以使用一个大开关并自己调用这些动作,但当然,我想避免这种情况。
我使用postEvent
作为接收者在sendEvent
内使用了eventFilter
和MainWindow
,但忽略了这些事件:
bool MainWindow::eventFilter(QObject*, QEvent* event) {
if (event->type() == QEvent::KeyPress) {
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Z
&& keyEvent->modifiers() == Qt::ControlModifier) {
//Calling the triggers directly works
ui->actionUndo->trigger();
return true;
} else if (keyEvent->modifiers().testFlag(
Qt::KeypadModifier)) {
QKeyEvent* ev2
= new QKeyEvent(keyEvent->type(), keyEvent->key(), 0);
qDebug() << keyEvent << ev2;
//This sendEvent doesn't work
QApplication::sendEvent(ui->widget, ev2);
event->accept();
return true;
} else {
return false;
}
}
return false;
}
答案 0 :(得分:3)
作为解决方案之一,您可以安装QEvent::ShortcutOverride个事件过滤器:
对于QEvent :: ShortcutOverride,接收器需要明确接受 触发覆盖的事件。在键事件上调用ignore() 将它传播到父窗口小部件。事件传播了 父窗口小部件链,直到窗口小部件接受它或事件过滤器 消耗它。
当某些小部件尝试覆盖快捷方式事件时,将调用该事件,例如,只是一个简单的例子:
我只有一个新的Qt应用程序,带有一个带有Ctrl + V快捷键的lineEdit和窗口菜单(覆盖了lineEdit中的粘贴快捷方式)。
这是如何运作的:
1.创建将忽略(返回true
)快捷方式覆盖的过滤方法(我在示例应用程序中使用了MainWindow::eventFilter
,但您可以使用您需要或想要的任何过滤对象)。最好跟随Qt文档并使用上面所述的accept()/ ignore(),但是在我的应用程序上它工作正常,没有它们只返回true / false。
2.将事件过滤器从p.1安装到小部件,如果覆盖,则应忽略快捷操作。
3.我已在设计器中使用Ctrl + V快捷键添加了菜单操作。在下面的代码中,当您尝试粘贴(Ctrl + V)而不是实际的lineEdit粘贴操作时,您会看到"Hello from window shortcut!"
- 菜单操作结果。
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->lineEdit->installEventFilter(this);
}
bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
if (event->type() == QEvent::ShortcutOverride) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
// Ignore only the Ctrl + V shortcut override, you can customize check for your needs
if (keyEvent->modifiers().testFlag(Qt::ControlModifier) && keyEvent->key() == 'V') {
qDebug() << "Ignoring" << keyEvent->modifiers() << "+" << (char)keyEvent->key() << "for" << watched;
event->ignore();
return true;
}
}
return QMainWindow::eventFilter(watched, event);
}
void MainWindow::on_action1_triggered()
{
qDebug() << "Hello from window shortcut!";
}
示例调试输出:
为QLineEdit忽略QFlags(ControlModifier)+ V(0x575b10,name =“lineEdit”)
来自窗口快捷方式的Hello!
注意:不幸的是,您应该为所有不希望手动覆盖快捷方式的小部件安装此类过滤器。
更新:很快 - 您忽略了基础窗口小部件快捷方式事件并将其传播到父窗口小部件。
下面是Ctrl-Z(在编辑时触发撤消)和Ctrl-V(在编辑中忽略而不是粘贴,触发菜单操作)的比较:
阻止I - 开始时的事件对于Ctrl-Z和忽略的Ctrl-V都是相同的:
第二组 - 差异发生的地方......
对于Ctrl-Z - lineEdit接收Ctrl + Z KeyPress事件,触发撤消操作:
QLineEdit收到QKeyEvent(KeyPress,Key_Z,ControlModifier)
这里MainWindow没有收到任何事件,不依赖于它是否有Ctrl + Z动作快捷方式,它只是被QLineEdit吞噬
对于Ctrl-V - MainWindow接收从QLineEdit传播的Ctrl + V ShortcutOverride事件:
filterEvent
“你好,从窗口快捷方式!”菜单中的代码已执行动作触发的插槽。
这里QLineEdit在过滤器告诉它忽略ShortcutOverride后没有收到任何事件,而是执行了MainWindow快捷方式
Block III - 结尾的事件对于Ctrl-Z和忽略的Ctrl-V也是相同的 - 只是关键的释放事件:
<强> P.S。我真的不知道为什么会发生这种情况 - 但这只是它的工作方式:)