Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct

    [Solved] How to propagate keyPressEvent on different qt QMainWindow

    General and Desktop
    2
    28
    50725
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • S
      stukdev last edited by

      I have 2 different QMainWindow, the first is the parent of the second. I want press some keys in the children windows and propagate the event in the parent. I create for everyone the function void keyPressEvent(QKeyEvent* event); but when i press key on the children the event is not propagate to the parent. Why?

      This is the code...

      //Parent class.h
      @#ifndef MAINWINDOW_H
      #define MAINWINDOW_H

      #include <QMainWindow>
      #include <QKeyEvent>
      #include "test.h"
      #include <QDebug>

      namespace Ui {
      class MainWindow;
      }

      class MainWindow : public QMainWindow
      {
      Q_OBJECT

      public:
      explicit MainWindow(QWidget parent = 0);
      ~MainWindow();
      protected:
      void keyPressEvent(QKeyEvent
      event);
      private:
      Ui::MainWindow *ui;
      test *form;

      private slots:
      void on_pushButton_clicked();
      };

      #endif // MAINWINDOW_H
      @

      //Parent class.cpp
      @
      #include "mainwindow.h"
      #include "ui_mainwindow.h"

      MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),ui(new Ui::MainWindow)
      {
      ui->setupUi(this);
      form = new test(this);
      }

      MainWindow::~MainWindow()
      {
      delete ui;
      }

      void MainWindow::keyPressEvent(QKeyEvent* event)
      {
      qDebug() << event->text();
      }

      void MainWindow::on_pushButton_clicked()
      {
      form->show();
      }
      @

      //Children class.h

      @
      ifndef TEST_H
      #define TEST_H

      #include <QMainWindow>
      #include <QKeyEvent>
      namespace Ui {
      class test;
      }

      class test : public QMainWindow
      {
      Q_OBJECT

      public:
      explicit test(QWidget parent = 0);
      ~test();
      protected:
      void keyPressEvent(QKeyEvent
      event);
      private:
      Ui::test *ui;
      };

      #endif // TEST_H
      @

      //children class.cpp

      @
      #include "test.h"
      #include "ui_test.h"

      test::test(QWidget *parent) : QMainWindow(parent), ui(new Ui::test)
      {
      ui->setupUi(this);
      }

      test::~test()
      {
      delete ui;
      }

      void test::keyPressEvent(QKeyEvent* event)
      {
      qDebug() << event->text();
      event->ignore();

      }
      @

      1 Reply Last reply Reply Quote 0
      • ?
        Guest last edited by

        In child class.cpp,

        Instead of ..
        @
        void test::keyPressEvent(QKeyEvent* event)
        {
        qDebug() << event->text();
        event->ignore();
        }
        @

        try something like this ...
        @
        void test::keyPressEvent(QKeyEvent* event)
        {
        qDebug() << event->text();
        ParentClassName::keyPressEvent(event); //this should pass the event to parent
        }
        @

        Are you doing something different in the keyPressEvent method of the child when compared to the parent? Do you need the keyPressEvent method in the child?

        1 Reply Last reply Reply Quote 0
        • S
          stukdev last edited by

          Did you mean this?
          @
          void test::keyPressEvent(QKeyEvent* event)
          {
          this->ui->l_key->setText(event->text());

          MainWindow *parentMain = (MainWindow *)this->parentWidget();
          parentMain->keyPressEvent(event);
          }
          @

          But this is easy and i have to declare public keyPressEvent in the parent, in the doc i read is qt that propagate the event! Not me!

          bq. Are you doing something different in the keyPressEvent method of the child when compared to the parent? Do you need the keyPressEvent method in the child?

          Yes in the real case i have the children get the event but i want use in the parent, for this i need propagate the event from children to the parent.

          1 Reply Last reply Reply Quote 0
          • ?
            Guest last edited by

            Hi,
            This might not be required,
            @
            MainWindow *parentMain = (MainWindow *)this->parentWidget();
            parentMain->keyPressEvent(event);
            @

            the below should work,
            @
            MainWindow::keyPressEvent(event);
            @
            also refer "The Event System":http://doc.qt.nokia.com/4.7/eventsandfilters.html docs

            1 Reply Last reply Reply Quote 0
            • S
              stukdev last edited by

              None, becouse this cause error in the build...

              cannot call member function 'virtual void MainWindow::keyPressEvent(QKeyEvent*)' without object

              1 Reply Last reply Reply Quote 0
              • ?
                Guest last edited by

                sorry my fault, try
                @
                QMainWindow::keyPressEvent(event);
                @

                1 Reply Last reply Reply Quote 0
                • S
                  stukdev last edited by

                  Ok, QMainWindow::keyPressEvent(event); but this not work! The parent not receive event!

                  What have to do this? Call the event for every QMainWindows in the program?

                  1 Reply Last reply Reply Quote 0
                  • ?
                    Guest last edited by

                    ok, I actually tried this just now, and here is my ChildWindow ... which inherits MainWindow and this snip works.. let me know :)

                    @
                    ChildWindow::ChildWindow(QWidget *parent) :
                    MainWindow(parent)
                    {
                    qDebug() << "ChildWindow constructor";
                    setFocusPolicy(Qt::StrongFocus);
                    }

                    void ChildWindow::keyPressEvent(QKeyEvent *event)
                    {
                    qDebug() << "ChildWindow::key pressed";
                    MainWindow::keyPressEvent(event);
                    }
                    @

                    1 Reply Last reply Reply Quote 0
                    • S
                      stukdev last edited by

                      bq. ok, I actually tried this just now, and here is my ChildWindow … which inherits MainWindow and this snip works.. let me know :)

                      Wait, in this children you have use MainWindow, not QMainWindow! Why?

                      1 Reply Last reply Reply Quote 0
                      • ?
                        Guest last edited by

                        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

                        1 Reply Last reply Reply Quote 0
                        • S
                          stukdev last edited by

                          Ok, but please use QMainWindow so is my example! And try if it run! Thank's for your time ^^

                          1 Reply Last reply Reply Quote 0
                          • ?
                            Guest last edited by

                            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?

                            1 Reply Last reply Reply Quote 0
                            • S
                              stukdev last edited by

                              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?

                              1 Reply Last reply Reply Quote 0
                              • ?
                                Guest last edited by

                                Is this your use case?

                                1. 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
                                2. 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?

                                1 Reply Last reply Reply Quote 0
                                • S
                                  stukdev last edited by

                                  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 QWidget

                                  Assuming 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 Father

                                  Is correctly or not?

                                  Thank's for your patiece...but i want clarify this topic :)

                                  1 Reply Last reply Reply Quote 0
                                  • ?
                                    Guest last edited by

                                    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); 
                                    

                                    }
                                    @

                                    1 Reply Last reply Reply Quote 0
                                    • S
                                      stukdev last edited by

                                      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]

                                      1 Reply Last reply Reply Quote 0
                                      • ?
                                        Guest last edited by

                                        let me try and get back

                                        1 Reply Last reply Reply Quote 0
                                        • ?
                                          Guest last edited by

                                          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 keypress

                                          but 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 keypress

                                          To 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().
                                          @

                                          1 Reply Last reply Reply Quote 0
                                          • S
                                            stukdev last edited by

                                            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!

                                            1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post