我有一个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;
}
Run Code Online (Sandbox Code Playgroud)
As one of the solutions you can install QEvent::ShortcutOverride event filters:
For QEvent::ShortcutOverride the receiver needs to explicitly accept the event to trigger the override. Calling ignore() on a key event will propagate it to the parent widget. The event is propagated up the parent widget chain until a widget accepts it or an event filter consumes it.
That event would be called when some widget tries to override a shortcut event, e.g. just a simple example:
I have just a new Qt app with one lineEdit and window menu with Ctrl+V shortcut (overrides the paste shortcut in lineEdit).
Here how it works:
1.Create the filtering method that would ignore (return true) the shortcut overrides (I've used MainWindow::eventFilter in sample app, however you can use any filtering object you need or want). It might be better to follow Qt docs and use the accept()/ignore() as stated above, however on my app it worked just fine without them just returning true/false.
2.Install the event filter from p.1 to widget that should ignore shortcut action if overriding.
3.I've added the menu action with Ctrl+V shortcut in designer. In code below you would see the "Hello from window shortcut!" - the menu action result, when trying to Paste (Ctrl+V) instead of actual lineEdit paste operation.
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!";
}
Run Code Online (Sandbox Code Playgroud)
Sample debug output:
Ignoring QFlags(ControlModifier) + V for QLineEdit(0x575b10, name = "lineEdit")
Hello from window shortcut!
Note: Unfortunatelly you should install such filters for all widgets you want not to override the shortcuts manually.
UPDATE: Shortly - you are ignoring the underlying widget shortcut event and propagating it to the parent widget.
Below is comparison for Ctrl-Z (triggers Undo in edit) and Ctrl-V (ignored in edit instead of Paste, and triggers menu Action):
Block I - events in beginning are the same for both Ctrl-Z and ignored Ctrl-V:
Block II - where the difference happens...
For Ctrl-Z - lineEdit receives the Ctrl+Z KeyPress event, triggering the Undo operation:
QLineEdit recieves QKeyEvent(KeyPress, Key_Z, ControlModifier)
Here the MainWindow recieves no events, not depending of has it Ctrl+Z action shortcuts or not, it's just swallowed by QLineEdit
For Ctrl-V - MainWindow receives the Ctrl+V ShortcutOverride event propagated from QLineEdit:
filterEvent"Hello from window shortcut!" code from menu Action triggered slot executed.
Here the QLineEdit receives no events after filter tells it to ignore ShortcutOverride, the MainWindow shortcut executed instead
Block III - events in ending are also the same for both Ctrl-Z and ignored Ctrl-V - just key release events:
P.S. I really don't know why it happens the exactly so - but this is just how it works :)