NaturalDemon
NaturalDemon

Reputation: 1014

How to make a lower class call a method of its parent?

I have followed this turorial Qt Creator + OpenGL and everything is going well.

I have added a QPlainTextEdit on top of the Quit button and I would like to have GLWidget send info back to MainWindow.

How can I make GLWidget call a function of the MainWindow?

Here is some code:

// GLWidget.h

class GLWidget: public QGLWidget
{
Q_OBJECT // <----- 
public:
    GLWidget(QWidget* parent = 0);
    QWidget* parentObject;
    void writeText( QString );
    void (*p)(QString) = NULL;
protected:
    virtual void initializeGL();
    virtual void paintGL();
    virtual void resizeGL(int w, int h);

private:
    QTimer timer;
signals:
    //void writeText( QString );
    void dataReady(QString data); // <------------------
};

// GLWidget.cpp

GLWidget::GLWidget(QWidget* parent) : QGLWidget() /7 <---- new error
{
    connect(&timer, SIGNAL(timeout()), this, SLOT(updateGL()));
    timer.start(16);


    QMessageBox msgBox;
    msgBox.setText(typeid(parent).name());
    msgBox.exec();



    //p = parent->
    //parentObject->
    //parent->
    //parent->
    //this->parentObject = parent;
}

void GLWidget::initializeGL(){
    //emit GLWidget::dataReady("myData"); //<--------- error
    emit this->dataReady("Joe");//<--------- same as above
    glClearColor(0.2, 0.2, 0.2, 1);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHTING);
    glEnable(GL_COLOR_MATERIAL);
}
    

// MainWindow.h

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void print(QString text);

private slots:
    void on_plainTextEdit_textChanged();
    void foo(QString data); // <----------------------
}
    
    

// mainwindow.cpp

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->widget->p = &MainWindow::print; // error, how to asign pointer?
}

void MainWindow::print(QString text){
    ui->plainTextEdit->setPlainText(text);
}

void MainWindow::foo(QString data) { // <---------
    QMessageBox msgBox;
    msgBox.setText("hi, there");
    msgBox.exec();
    // Do something with the data
    ui->plainTextEdit->setPlainText(data);
}

error:

Upvotes: 1

Views: 101

Answers (1)

scopchanov
scopchanov

Reputation: 8399

Here is the answer to your immediate question, How to make a lower class exploit a function in it's parent?:

All QObject subclasses hold a reference to their parent object, accessible through the parent() method.

  1. Include the header of the parent's class, e.g Foo.h
  2. Call the parent() methodd to obtain a pointer to the object's parent
  3. Check if the pointer is valid (not a nullptr)
  4. Cast the pointer to the parent's class, e.g. Foo
  5. Call the desired method, e.g. foo

In code it looks like this:

#include "Foo.h"

...

if (parent())
    static_cast<Foo *>(parent())->foo();

That being said, this creates a tight coupling between the parent and the child and I strongly advise to avoid doing it if possible. In your case would be much better to use signals and slots to communicate the data from the child to the parent:

  1. Define a signal in the child, e.g. dataReady(DataType data)
  2. In the parent, when you create the child, connect this signal to the method, which will use the data, e.g. foo
  3. In the child, emit the signal, whenever you feel like calling foo

In code it looks like this:

Child.h

...
signals:
    void dataReady(DataType data);
...

Child.cpp

...
// I want to call foo
emt dataReady(myData);
...

Parent.h

...
private slots:
    void foo(DataType data);
...

Parent.cpp

...
//somewhere
auto *child = new Child(...);
connect(child, &Child::dataReady, this, &Parent::foo);

...

void Parent::foo(DataType data) {
    // Do something with the data
    ...
}
...

This requires more work initially, but it is much better in a long-term.

Upvotes: 2

Related Questions