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]
-
gBox->installEventFilter(this); gBox->installEventFilter(this); gBox->installEventFilter(this);
do you see it? ;)
-
@NIXIN
sosomesignal1()
andsomesignal2()
will only be emitted when the corresponding buttons also have the focus while you press the F1-key. -
@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. -
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.
-
@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.
-
@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.