Search code examples
qtqwidget

QWidget::resizeEvent() not called in a sub subclass


I have the following snippet:

    class A : public QWidget
    {
       Q_OBJECT
   public:
     A(QWidget *parent = 0);

     void
     setGeometry(int x, int y, int w, int h);

      protected:
       virtual void
       resizeEvent(QResizeEvent *event);

    }

    class B : public A
    {
       Q_OBJECT
   public:
     B(A*parent = 0);   

     void
    setGeometry(int x, int y, int w, int h);

   protected:
     virtual void
     resizeEvent(QResizeEvent *event);
    }

void
A::setGeometry(int x, int y, int w, int h) 
{
    QWidget::setGeometry(x, y, w, h);
}

void
A::resizeEvent( QResizeEvent * event) 
{
    QWidget::resizeEvent(event);
    // common A and B stuff
}

void
B::setGeometry(int x, int y, int w, int h) 
{
    A::setGeometry(x, y, w, h);
}

void
B::resizeEvent( QResizeEvent * event) 
{
    A::resizeEvent(event);

}

Calling setGeometry on an instance of A will fire resizeEvent() . Invoke setGeometry on an instance of B will not fire resizeEvent(). Is there anything wrong with this?

EDIT: I could do the same calculation I need inside setGeometry successfully. Now, mine is only curiosity.


Solution

  • There are a few problems with the snippet above, so I've altered it in a few places... the code below is the minimum necessary to produce the behaviour you want.

    Header:

    class TestA : public QWidget
    {
      Q_OBJECT
    
      public:
        explicit TestA(QWidget *Parent = 0) : QWidget(Parent) {}
        ~TestA() {}
    
      protected:
        virtual void resizeEvent(QResizeEvent *);
    };
    
    class TestB : public TestA
    {
      Q_OBJECT
    
      public:
        explicit TestB(QWidget *Parent = 0) : TestA(Parent) {}
        ~TestB() {}
    
      protected:
        virtual void resizeEvent(QResizeEvent *);
    };
    

    Implementation:

    void TestA::resizeEvent(QResizeEvent *)
    {
      qDebug() << "TestA Resize";
    }
    
    void TestB::resizeEvent(QResizeEvent *)
    {
      qDebug() << "TestB Resize";
    }
    
    MainWindow::MainWindow(QWidget *parent) :
      QMainWindow(parent),
      ui(new Ui::MainWindow)
    {
      ui->setupUi(this);
    
      TestA* A = new TestA(this);
      TestB* B = new TestB(this);
    
      A->setGeometry(0,0,100,100);
      B->setGeometry(200,200,100,100);
    }
    

    Changes:

    • Addition of Q_OBJECT macros to class definition:

      Tells the compiler to add Qt meta-object code for the class (not strictly necessary to ensure that resizeEvent()s are called, but should be included for objects which inherit QObject as a matter of course).

    • Addition of constructors which allow the passing in of a parent object and invoke the base class constructor with this parent object AND passing a parent object into the constructors of the two objects when they are created:

      From the docs:

      When changing the geometry, the widget, if visible, receives a move event (moveEvent()) and/or a resize event (resizeEvent()) immediately. If the widget is not currently visible, it is guaranteed to receive appropriate events before it is shown.

      If your widgets don't have parents setting the geometry is half meaningless, as the x and y parts refer to its position relative to a parent. On top of that, since the widgets have no parents they can't be visible as part of the application so Qt doesn't bother to call the appropriate resizeEvent().