QPushButton default in not QDialogBox widget
-
If I make some button, which belongs to QDialogBox "default", i can hit it by pressing "Enter".
Now I have another problem: there is a "form" (QDockWidget, but any QWidget should do), with QComboBox-es and other standard interactive widgets and one "submit" QPushButton at bottom. What I want is that "submit" button is pressed whenever i press "Enter" while any of form's widget is having focus.
What is the best way to do this, except catching "Enter pressed" events for every widget in form separately and transferring it to "submit" button?
I tried making "submit" button default - does not help, it must have focus to be pressed with "Enter" key. I can not setProxyFocus(submitButton) for other widgets in the form, because QLineEdit will not allow input if it does not have a focus. -
install an event filter for the widget parent and listen for Return key press event and then either sendEvent to the submit button or call directly submit function: any child widget having focus will notify the parent widget on its input events
-
you can try this:
@
QAction* action = new QAction(formWidget);
action->setShortcut( QKeySequence("Enter") );
action->setShortcutContext( Qt::WidgetWithChildrenShortcut );
connect(action, SIGNAL(triggered()), button, SLOT(click()));
formWidget->addAction(action);
@ -
[quote author="NicuPopescu" date="1383836436"]install an event filter for the widget parent and listen for Return key press event and then either sendEvent to the submit button or call directly submit function: any child widget having focus will notify the parent widget on its input events[/quote]
This only works when the child widget doesn't accept the ENTER key event! It's not guaranteed that the parent will receive the event. -
[quote author="raven-worx" date="1383836834"]you can try this:
@
QAction* action = new QAction(formWidget);
action->setShortcut( QKeySequence("Enter") );
action->setShortcutContext( Qt::WidgetWithChildrenShortcut );
connect(action, SIGNAL(triggered()), button, SLOT(click()));
formWidget->addAction(action);
@[/quote]
Thank you for your suggestion, but unfortunately it does not seem to work. Action is never triggered. -
[quote author="Daylight" date="1383837644"]
Thank you for your suggestion, but unfortunately it does not seem to work. Action is never triggered.[/quote]
Any output on the console?
Are you sure you hitting the right ENTER key? I mean did you probably mix it up with the RETURN key? -
bq. This only works when the child widget doesn’t accept the ENTER key event! It’s not guaranteed that the parent will receive the event.
how you mean "doesn't accept"? the filter is for parent widget! :)
bq. The documentation for QCoreApplication::notify() concisely tells the whole story
-
QCoreApplication::notify() kicks in just before any eventFilter is gets called.
By accepting i mean the parent widgets only receives the event (and thus also the event filters installed on it) when any child widget propagates it to the parent widget by not "accepting":http://qt-project.org/doc/qt-4.8/qevent.html#accept it. When it's was accepted by the child widget the event wont be propagated further up the parent hierarchy. -
[quote author="raven-worx" date="1383839045"]
Any output on the console?
Are you sure you hitting the right ENTER key? I mean did you probably mix it up with the RETURN key?
[/quote]
No, no output on the console. I have tried both "Return" below the "Backspace" and "Enter" at the numpad. -
bq. QCoreApplication::notify() kicks in just before any eventFilter is gets called.
By accepting i mean the parent widgets only receives the event (and thus also the event filters installed on it) when any child widget propagates it to the parent widget by not accepting [qt-project.org] it. When it’s was accepted by the child widget the event wont be propagated further up the parent hierarchy.I'm talking on qt default behavior for event propagation, mainly for os generated events like key events ... but saying that is not guaranteed the parent widget will receive the event because we could do a child widget accepting an event (similar with returning true in a filter) is not qt statement, is not qt default behavior ... what I want to say is that qt guarantees that child widgets key events are propagated to the parent, they will treat the events in their window procedures and will not consume(accept) event as QEvent by default ...
anyway what I say is tested and used for many times and I would be surprised to be other way :)
-
@Daylight : pls try in a simple main window app:
in constructor:
ui->lineEdit->parentWidget()->installEventFilter(this);
lineEdit = any widget
@bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::KeyPress)
{QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event); if(keyEvent->key() == Qt::Key_Return ||keyEvent->key() == Qt::Key_Enter) { qDebug()<<"receiver"<<obj->objectName(); qDebug() << "MainWindow::eventFilter..."; } } return QObject::eventFilter(obj, event);
}@
and see what happens ...
-
[quote author="NicuPopescu" date="1383841588"]
and see what happens ...[/quote]well of course your example is working in this particular... that's just because you are doing it with a QLineEdit. Why should a QLineEdit widget accept the a key event for ENTER or RETURN keys?! Thus the key events are propagated since they do not get accepted by the QLineEdit because it doesn't consume it.
Try your example with a QTextEdit for example and you see what happens...
You will see that it is important which widget you are using and not as stated in your example "any widget".Even in the QKeyEvent docs this is mentioned:
[quote]
A key event is propagated up the parent widget chain until a widget accepts it with accept() or an event filter consumes it.
[/quote] -
I would say that rather QTextEdit is a particular case as most, I reckon not "any", widgets ignore() key press events(by default QEvent has accepted flag) in as default implementation
if the same filter is installed for QTextEdit and first for this objects will be cleared the accepted flag then the common eventFilter() will receive key events ... at first proposal, I didn't want to mention that instead installing once a filter for parent widget, for possible inconveniences, it could be considered to install the same filter for any widget from which a submit action should be triggered ...
bq. Why should a QLineEdit widget accept the a key event for ENTER or RETURN keys?!
... perhaps if it has a completer, and this is default implementation when a completer is in place
-
[quote author="NicuPopescu" date="1383922373"]I would say that rather QTextEdit is a particular case as most, I reckon not "any", widgets ignore() key press events(by default QEvent has accepted flag) in as default implementation
[/quote]
yes it's initially set to accepted, but the default event handler implementations in QWidget call ignore() ! Meaning that when the widget decides to consume it it accepts it (like QTextEdit)[quote author="NicuPopescu" date="1383922373"]
if the same filter is installed for QTextEdit and first for this objects will be cleared the accepted flag then the common eventFilter() will receive key events ... at first proposal, I didn't want to mention that instead installing once a filter for parent widget, for possible inconveniences, it could be considered to install the same filter for any widget from which a submit action should be triggered ...
[/quote]
i didn't say it wouldn't work. i said it's not guaranteed that it will work in all cases and that's a fact.[quote author="NicuPopescu" date="1383922373"]
... perhaps if it has a completer, and this is default implementation when a completer is in place[/quote]
Then the completer accepts the event and not the widget, since the completer installs itself as event filter on the widget.Lets end this discussion here since it is drifting away from the thread's topic and it wont change my mind about event propagation ;)
-
bq. yes it’s initially set to accepted, but the default event handler implementations in QWidget call ignore() ! Meaning that when the widget decides to consume it it accepts it (like QTextEdit)
that's not accurate since QWidget's keyPressEvent is virtual and we talk about its specialized classes ...
bq. Then the completer accepts the event and not the widget, since the completer installs itself as event filter on the widget.
imho I think this is not accurate too! ... please check source code for QLineEdit, QCompleter and qlinewidgetcontrol.cpp and you'll find out the completer's event filter does not accept() key press events and in fact is done in other place in qlinewidgetcontrol.cpp
bq. Lets end this discussion here since it is drifting away from the thread’s topic and it wont change my mind about event propagation ;)
:) ... eh, I close my eyes ... in which way I'm off topic: I believe that solution with filter is one of the best for the issue ... is there other one around and I not see? :)
bq. What is the best way to do this, except catching “Enter pressed” events for every widget in form separately and transferring it to “submit” button?
... Daylight just wants to write less code and do more