[Solved]Priority of QKeySequence over keyPressEvent



  • Dear Qt-ers,
    I need to bind the Return key to a QAction. I have done this with
    @actionStartMeasure->setShortcut(Qt::Key_Return);@ Now I have some side-effects with both standard and custom widget.
    If the user press Enter when a QComboBox has focus, it will select the current entry in the combobox and trigger the QAction.
    If I create a new widget and reimplement keyPressEvent(), I never enter this function it when the Enter key is pressed.

    How can I deal with that. Is there some place where the priorities of shortcut handling are explained?
    I see I have a 3rd option: creating a QShortcut and connecting it to my QAction. Again: how are priorities handled?



  • How about using an eventFilter() for your applicaiton where you can set newWidget->installEventFilters(this) and you can check based on the target value eg.

    @bool MainWindow::eventFilter(QObject *target, QEvent *event)
    {
    if (target == newWidget && event->type() == QEvent::KeyPress)
    {
    QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
    if (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return)
    {
    //do something
    return QMainWindow::eventFilter(target,event);
    }
    }
    return QMainWindow::eventFilter(target,event);
    }@



  • -This way, i would not catch all the "Enter" events that have been accepted by child widgets?-
    Hum sorry I read too quickly.
    I don't understand: which widgets do you suggest me to install this filter on?



  • You can install the eventFilter on your custom widget.

    bq. If I create a new widget and reimplement keyPressEvent(), I never enter this function it when the Enter key is pressed.

    For an example you can check "here":http://qt-project.org/doc/qt-5.0/qtcore/qobject.html#eventFilter



  • I know how to install events. Other keystroke do work. The problem occurs with the "Return" key that is somehow eaten by the global shortcut. With your suggestion, you think I can keep my global shorcut and still receive "enter" event on my custom widget? I will try but I don't think so.
    Will end up with the same problem than when reimplementing keyPressEvent, won't I?



  • Still struggling with that question.


  • Moderators

    i think you need to listen to the QEvent::ShortcutOverride event (which is a QKeyEvent) and trigger your action manually.
    Did you additionally set a shortcut context of the shortcut set on your action?



  • Thanks a lot for your answer.
    I played with shortcut context on my QAction, but it only work as intended with the default value.
    I will have a look at your suggestion.
    So you are telling me that my widget (in this case the QLineEdit) will receive a ShortcutOverride event when the Return key is pressed?
    Or that I should remove my "global" shortcut and listen to ShortcutOverride on the mainwindow instead?


  • Moderators

    You will only receive a ShortcutOverride event when there is a shortcut disambiguation.
    If no disambiguation is detected a normal shortcut event is sent and the action is triggered normally (as one would expected).
    Note: ShortcutOverride events aren't handled in Qt by default.

    I'm not 100% sure if your line edit will receive the shortcut override event, but i think so. At least it would make sense IMHO.
    But to make sure you can install an event filter on the QApplication and check which widget receives the shortcut override event initially.



  • Cool, that did the trick when I installed it on my QLineEdit.
    Would be could if I could install it once on the QMainWindow and check if the receiver is a QSpinBox, QComboBox or QLineEdit.
    However when I try that, the object returned in
    @eventFilter(QObject *obj, QEvent *event)@ is always a QMainWindow


  • Moderators

    did you install the main window on the widgets you want to inspect as an event filter?
    Alternatively as i said you can install the main window on the QApplication object and check there if the watched is one of your widgets.
    @qApp->installEventFilter(mainWin);@



  • Ok in the mean time I tried to install in on the qApp instead of the QMainWindow.
    I now enter the eventFilter for all successive widgets that sees the keypressEvent propagation.
    How do I stop this propagation? Returning true does not stop it.
    @bool ApplicationMonitor::eventFilter(QObject *obj, QEvent *event)
    {
    if (event->type() == QEvent::ShortcutOverride )
    {
    QKeyEvent *ev = static_cast<QKeyEvent *>(event);
    if( ev->key()==Qt::Key_Return || ev->key()==Qt::Key_Enter )
    {
    qTrace(obj->metaObject()->className());
    return true;
    }
    }
    // standard event processing
    return QObject::eventFilter(obj, event);
    };@
    [quote]TRACE 19/04/13 12:07:33 - QDoubleSpinBox
    TRACE 19/04/13 12:07:35 - QWidget
    TRACE 19/04/13 12:07:35 - QDockWidget
    TRACE 19/04/13 12:07:35 - MainWindows[/quote]


  • Moderators

    @event->accept() //stops event propagation@

    But in your code you don't check the watched object against your widget objects.



  • Thanks again, your help is greatly appreciated! I'm not sure why the doc for eventFilter() says
    [quote]In your reimplementation of this function, if you want to filter the event out, i.e. stop it being handled further, return true; otherwise return false.[/quote]
    Should I do both: accept it and return true?

    If the object is not a QLineEdit, should I return false and reject the event? Or just return false?

    Last question: In order to filter on receiver what is best in terms of perfomances.
    @obj->metaObject()->className()=="QLineEdit"
    QLineEdit* le = dynamic_cast<QLineEdit*>(obj)@


  • Moderators

    [quote author="Julien M" date="1366366563"]
    If the object is not a QLineEdit, should I return false and reject the event? Or just return false?
    [/quote]
    Best would be todo nothing of both :)
    You just want to inspect and trigger your action in case and don't want to manipulate the event chain at all.

    [quote author="Julien M" date="1366366563"]
    Last question: In order to filter on receiver what is best in terms of perfomances.
    @obj->metaObject()->className()=="QLineEdit"
    QLineEdit* le = dynamic_cast<QLineEdit*>(obj)@[/quote]
    Best would be to hold pointers to your widgets and jsut do a pointer comparison. Thats the fastest way. Don't use dynamic_cast, only if you really have to, since the it has a large performance impact.



  • [quote author="raven-worx" date="1366366885"]Best would be todo nothing of both :)
    You just want to inspect and trigger your action in case and don't want to manipulate the event chain at all.[/quote]No, in fact what I'm trying to do now is:

    • Keep my "Return" QShortcut on a QAction
    • Prevent some specific widget types (eg. QLineEdit) to trigger this QAction when the user press Return in them

    So my eventFilter won't trigger the action but "forbid triggering in some case" instead.


  • Moderators

    ah yes...sorry.
    Nevertheless did you try already try to accept the event and if necessary also return true in the event filter?



  • Finally did that: @event->accept(); // Prevent event propagation to parents
    return false; // Allow obj to handle the "Enter" event@

    Thanks a lot for your help raven-worx!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.