[Solved] How to propagate keyPressEvent on different qt QMainWindow
-
yes, child is passing event to its parent which is MainWindow, and in MainWindow, if you have custom event handler, you can still pass it to its base class which would be QMainWindow
-
Ok, assume that in each class keyPressEvent() we display a "inside ClassName::keypressed" message using qDebug(),
then in ChildWindow::keyPressEvent() if you pass the event to MainWindow::keyPressEvent(), then output would be
@
inside ChildWindow::keypressed
inside Mainwindow::keypressed
@but if you directly pass the event to QMainWindow::keyPressEvent(), then output would be
@
inside ChildWindow::keypressed
@the second one would bypass its parent MainWindow and go directly to QMainWindow ...
does that clarify?
-
Yes i understand what did you say, but i not understand how can i resolve my problem without modify the inherit of the children class.
You change the inherit from QMainwindow to Mainwindow...and ok works.
But i don't want change this. Is there another solution?
-
Is this your use case?
- User presses key on child window, key event is received in child window, you do some custom action here and then pass the event to child window's parent window i.e. MainWindow
- MainWindow receives the event, does some custom action and consumes the event, i.e. does not pass it to its base class which is QMainWindow
is my understanding correct?
-
Yes is correct, but in your example your children inherit MainWindow not a QMainWindow. In my application my children inherit QMainWindow! I actually don't understand if there is some connection about the class inherit. Why you not create an example but inherit QMainWindow in childrean? Please try this and tell me if it work.
For what i've understand i want (this is an example for understand what i mean) create 3 class.
Class 1 GranFather inherit QMainWindow
Class 2 Father inherit QDialog
Classe 3 Children inherit QWidgetAssuming that scheme GranFather->Father->Children
so the parent of Father is GranFather, the parent of Children is Father...
in costructor of class the parent want a QWidget, but this is not a problem becouse QMainWindows and QDialog inherit QWidget.So...every class have their keyPressEvent... with qDebug() << "NameClass".
Now i want send to GranFather the task that i put into a Children!In the documentation of qt event, i read that is a qt event framework that propagate the event children to parent... if nobody accept() the event!
So if in the children i write in a keyPressEvent() function a ignore->event() i'm expecting that the event is propagate to Father... if the father ... ... ignore->event() ... ... event is propagate to GranFather.
For what you have wrote in this post i have to put in the keyPressEvent in a childrean class this code
QMainWindow::keyPressEvent(event); //for a GranFather
QDialog::keyPressEvent(event); //For a FatherIs correctly or not?
Thank's for your patiece...but i want clarify this topic :)
-
Ok I get it now ... :)
stuk:
bq.
In the documentation of qt event, i read that is a qt event framework that propagate the event children to parent… if nobody accept() the event!Can you point out the exact link where you read this? To my knowledge if an object does not handle an event, it is passed to its base class. I think you are talking about parent widget and I'm talking about parent class or base class.
For your scenario to work, your earlier code should do the trick: you mentioned it worked right?
@
void test::keyPressEvent(QKeyEvent* event)
{
this->ui->l_key->setText(event->text());MainWindow *parentMain = (MainWindow *)this->parentWidget(); parentMain->keyPressEvent(event);
}
@ -
Yes, i mean the parentWidget! from "http://labs.qt.nokia.com/2006/05/27/mouse-event-propagation/":http://labs.qt.nokia.com/2006/05/27/mouse-event-propagation/
(ok is tell about mouse event but i think is simil to key event)bq. Say you implement your own mouse event handling. If you ignore the mouse press event in mousePressEvent() by calling event->ignore(), it will first be mapped to your widget’s parent geometry (QWidget::mapToParent()), and then sent to the parent widget. In turn, your parent can also ignore the event, in which case the event will be resent to your parent’s parent widget, and so on. This is what we call event propagation; the event is “propagated to parent”.
So i not understand?
[edit: fixed link / chetankjain]
-
let me try and get back
-
Thanks for the link earlier. I am able to pass key event to parent widget by using ignore() ...
My code below ...This is MyWindow class, where on an event I open MyDialog
@
void MyWindow::clik()
{
mydial = new MyDialog(this);
mydial->setGeometry(QRect(40,40,200,200));
mydial->show();
}void MyWindow::keyPressEvent(QKeyEvent *event)
{
qDebug() << "Inside MyWindow keypress";
}
@This is MyDialog class where I have a child widget MyButton
@
MyDialog::MyDialog(QWidget *parent) : QDialog(parent)
{
qDebug() << "MyDialog constructor";
btn = new MyButton(this);
btn->setGeometry(QRect(5,5,40,40));
btn->show();
}void MyDialog::keyPressEvent(QKeyEvent *event)
{
qDebug() << "Inside MyDialog keypress";
event->ignore();
}
@This is MyButton class where I shift focus and then press a key
@
MyButton::MyButton(QWidget *parent) : QPushButton(parent)
{
qDebug() << "MyButton constructor";
setText("Hellllo");
}void MyButton::keyPressEvent(QKeyEvent *event)
{
qDebug() << "Inside MyButton keypress";
event->ignore();
}
@In this code, the key event on MyButton, is successfully ignored and passed to MyDialog, output is
Inside MyButton keypress
Inside MyDialog keypressbut the event does not then pass to MyWindow !!!
Next I added another MyButton to MyWindow, and pressed a key, there and it works! Ouput is
Inside MyButton keypress
Inside MyWindow keypressTo dig further, I see that QDialog has already reimplemented keyPressEvent, so I don't think the event will pass to its parent widget. But using the workaround earlier, you can explicitly pass the event to parent. Still digging further ...
@
void QDialog::keyPressEvent ( QKeyEvent * e ) [virtual protected]
//Reimplemented from QWidget::keyPressEvent().
@ -
Good news! Maybe there is a bug in some class that not propagate the event to the parent widget! My problem is using a QMainWindow, you have use QDialog. I try some other class to control this strange case.
When you write
bq. But using the workaround earlier, you can explicitly pass the event to parent.
you refer to use this?@MainWindow *parentMain = (MainWindow *)this->parentWidget();
parentMain->keyPressEvent(event);@bq. To dig further, I see that QDialog has already reimplemented keyPressEvent, so I don’t think the event will pass to its parent widget.
Yes, but also QPushButton have their keyPressEvent reimplement from QWidget!
-
I try some other class to control this strange case.
Yes, when I tried with QListWidget and also QPushButton, it was able to propogate to the MainWindow parent widget.
you refer to use this?
yes, that works for you right?Yes, but also QPushButton have their keyPressEvent reimplement from QWidget!
I stand corrected.Maybe there is a bug in some class that not propagate the event to the parent widget
I'm not sure if this is a bug. The window flags for a Dialog and Popup make it a top-level window. I think the intended behavior is so. So you have to use the workaround you mentioned earlier.
But, if you override the window flag of the dialog and set it to Qt::Widget, the events get propagated, but the UI behaviour of course changes. :) -
bq. es, that works for you right?
Yes, but with that workaround i call directly the function of the parent and i get to set public in a parent.
bq. The window flags for a Dialog and Popup make it a top-level window. I think the intended behavior is so. So you have to use the workaround you mentioned earlier.
But, if you override the window flag of the dialog and set it to Qt::Widget, the events get propagated, but the UI behaviour of course changes.Yes, but setting Qwidget flag deform my window form ( i try in the example posted and the result is one window that incorporate the two form!) and setting other such a QWindow or QDialog block the event.
Maybe, there are some Qt Troll that can post their impression about this, but i think they are at Qt Developer Days :)
-
yes now even i'm curious to know what they'd say :)
-
Well, after few days i think that QMainWindow is a top windows,for me QMainWindow is a event end, and maybe this is the problem because the event is not propagate!
Maybe there are some class such as QMainWindow,QDialog ecc.. that prevent the propagation of the event.If i want propagate the event i have to create an eventFilter on a parentWidget, and install it on a children. See "doc":http://doc.qt.nokia.com/4.7/eventsandfilters.html#event-filters
Now the code of the example is this:
//In the parent
@bool MainWindow::eventFilter(QObject *object, QEvent *event)
{
if (object == form && event->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
qDebug() << "event from children";
MainWindow::keyPressEvent(keyEvent); //Use the event in parent using its keyPressEvent()
return QObject::eventFilter(object, event);
}return QObject::eventFilter(object, event);
}
@//Children
@test::test(QWidget *parent) : QMainWindow(parent), ui(new Ui::test)
{
ui->setupUi(this);this->setWindowFlags(Qt::Dialog); this->installEventFilter(parent); //Installing the filter
}@
This is not very easy but clean, and work :)
But now qt developer days are end and i want a comment of a qt troll about this long post :)
-
yes this is definitely cleaner :) thanks for the post
-
Hello all,
Indeed the events are propagated to the parent but it stops to the top level parent (ie. the window). This is to make sure that all events get sensibly propagated tovisual parents.
So if you want to propagate a key event from on main window to another one, you'll have to do it manually. -
thanks for the clarification Thierry :)
-
bq. Hello all,
Indeed the events are propagated to the parent but it stops to the top level parent (ie. the window). This is to make sure that all events get sensibly propagated tovisual parents.
So if you want to propagate a key event from on main window to another one, you’ll have to do it manually.Thank's thierry, this tips is in the documentation of qt?