How to handle keypress event for all child widgets, in Qt?



  • I want to handle keypress event for all the child widgets, for which I am trying something like below:

    Widget::Widget(QWidget *parent):QWidget(parent)
    {
        QGroupBox *gBox = new QGroupBox(this);
    
        QPushButton *button1 = new QPushButton("1");
        QPushButton *button2 = new QPushButton("2");
    
        QVBoxLayout *vBox = new QVBoxLayout;
        vBox->addWidget(button1);
        vBox->addWidget(button1);
        gBox->setLayout(vBox);
    
        gBox->installEventFilter(this);
        button1->installEventFilter(this);
        button2->installEventFilter(this);
    }
    
    bool Widget::eventFilter(QObject *obj, QEvent *event)
    { 
    if (event->type() == QEvent::KeyPress)
    {
        if(obj == gBox)
        {
            QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
            if(keyEvent->key() == Qt::Key_F1)
            {
                emit somesignal();
            }
        }
       if(obj == button1)
       {
            QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
            if(keyEvent->key() == Qt::Key_F1)
            {
                emit somesignal1();
            }
       }
       if(obj == button2)
       {
            QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
            if(keyEvent->key() == Qt::Key_F1)
            {
                emit somesignal2();
            }
        }
    }
    return QObject::eventFilter(obj, event);
    }
    

    But whwnever I press F1, only somesignal() is emitted. I want to emit somesignal1(), somesignal2() also, for button1 and button2.

    Can somebody help me to achieve this?

    [Edit: Added code tags ~kshegunov]


  • Moderators

    gBox->installEventFilter(this);
    gBox->installEventFilter(this);
    gBox->installEventFilter(this);
    

    do you see it? ;)



  • sorry for the typing error, I have changed it.

    Now please help


  • Moderators

    @NIXIN
    so somesignal1() and somesignal2() will only be emitted when the corresponding buttons also have the focus while you press the F1-key.



  • what kind of focus

    can please provide a small code as an example


  • Moderators

    @NIXIN
    there is only one kind of (input-)focus.
    Only the focused widget receives input events (like key and mouse events). When they do not process them, the event is delivered to it's parent widget, and so on and on.

    Either you set the focus manually using QWidget::setFocus(), or by mouse or tab key navigation, etc.

    I think in your case its anyway better to use QShortcut instead of this eventFilter approach:

    QShortcut* shortcut = new QShortcut(QKeySequence("F1"), this, SLOT(onF1ShortcutTriggered()), SLOT(onF1ShortcutTriggered()), Qt::WindowShortcut)
    

    And just add a onF1ShortcutTriggered() slot to your class.



  • If I am using eventFilter(), then where should I implement this QWidget::setFocus()


  • Moderators

    it seems to me that you don't quite understand what the "focus" means yet.
    It's rather uncommon to set the focus just so you might (or might not) receive a shortcut key-press on a widget.

    Maybe you should explain more what you want to achieve exactly.



  • suppose there are several children widgets(here button1, button2) inside parent widget(here gBox). I want to provide help feature for these widget, such that if F1 is pressed for a particular widget it will emit a signal and html page will be opened in the corresponding slot.


  • Moderators

    @NIXIN
    well and why dont you accept my suggested approach using QShortcut?!
    You can even set a different QShortcut for every widget, with a different signal:

    new QShortcut(QKeySequence("F1"), button1, SIGNAL(somesignal1()), SIGNAL(somesignal1()), Qt::WidgetShortcut);
    new QShortcut(QKeySequence("F1"), button2, SIGNAL(somesignal2()), SIGNAL(somesignal2()), Qt::WidgetShortcut);
    ...
    

    Basically there is nothing wrong with the event filter approach and this approach works the same, since (like every other approach) needs the focus on the widget. And it is a one-liner. Which makes also perfect sense.

    Maybe the "Whats this" feature is of interest for you. This is rather focus independent, but also works differently.



  • I tried your suggested approach of using QShortcut

    Pressing F1, is working for parent widgets also.

    I want spacifically for child widget only


  • Moderators

    @NIXIN
    as i said...this only works if the button has input focus.
    This is mostly the case when the user clicked on it.

    An alternative is that you show the help according to the current mouse position at the time F1 is pressed. For that you can do this:

    qApp->installEventFilter( this );
    ...
    bool eventFilter( QObejct* watched, QEvent* event )
    {
        switch( event->type() )
        {
              case QEvent::KeyPress:
              {
                      QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
                      if(keyEvent->key() == Qt::Key_F1)
                      {
                             if( QWidget* w = QApplication::widgetAt( QCursor::pos() ) )
                             {
                                     if( w == XXX )
                                     {
                                            // show help
                                            return;
                                      }
                             }
                      }
              }
              break;
         }
    
         return BaseClass::eventFilter( watched, event );
    }
    

    don't know if thats enough for you.



  • That worked fine, thanx a lot for your help


Log in to reply
 

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