4

I'm trying to access the ui member which is private in the MainWindow class.

I would like to update a lineEdit (Xvaldisp) when I release the mousebutton (with the amount the mouse moved)from a gl widget.

After searching a bit around I found that I need to create a function/Method in mainwindow then access it through a pointer to Mainwindow from my GLWidget

The problem:

The lineEdit remains blank, The method( displaymessage() ) that should update it seems to get called.

To check that I've created a string(str) to see if displaymessage was getting called, this string gets updated with a new value when displaymessage() gets called.

The on_Button_clicked() method below displaymessage() also updates the same lineEdit when a pushbutton is clicked and works just fine it displays the content of str

Here's my code:

glwidget.h

#ifndef GLWIDGET_H
#define GLWIDGET_H

#include <QGLWidget>
#include <QTimer>
#include <QMouseEvent>
#include "mainwindow.h"
#include <QObject>
#include <QLineEdit>



class GLWidget : public QGLWidget
{
Q_OBJECT


public:

    explicit GLWidget(QWidget *parent = 0);


void mousePressEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);

void initializeGL();
void paintGL();
void resizeGL(int w, int h);

private:

    QTimer timer;

QPoint pointMpressed;
QPoint diff;


protected:


signals:
    void valueCh();     


    };

    #endif // GLWIDGET_H

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QLineEdit>
#include <QObject>

#include "glwidget.h"

namespace Ui {
    class MainWindow;
}


class MainWindow : public QMainWindow {
    Q_OBJECT


public:
    MainWindow(QWidget *parent = 0);
   ~MainWindow();




public slots:


   void on_Button_clicked();
   void displayMessage();


protected:
    void changeEvent(QEvent *e);


private:
    Ui::MainWindow *ui;

};




#endif // MAINWINDOW_H

glwidget.cpp.

#include "glwidget.h"
#include <GL/glut.h>



GLWidget::GLWidget(QWidget *parent) :
    QGLWidget(parent)
{

    connect (&timer,SIGNAL(timeout()),this,SLOT(updateGL()));
    timer.start(16);


}

void GLWidget::mousePressEvent(QMouseEvent *e){

    pointMpressed=e->pos();


}

void GLWidget::mouseReleaseEvent(QMouseEvent *e){

    diff=(e->pos())- pointMpressed ; //calculate position difference between click  and release


    MainWindow *mwd;

        mwd=  new MainWindow;


    //  mwd->displayMessage();   //tried this first then with signals and slots below same result

        QObject::connect(this, SIGNAL(valueCh()), mwd ,SLOT(displayMessage()) );

    emit valueCh();


   delete mwd;


    }


void GLWidget::initializeGL(){


}



void GLWidget::resizeGL(int w, int h){


}

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "glwidget.h"



QString str="none activated";  //I used this string to check if the methods were getting called




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

}



MainWindow::~MainWindow()
{

    delete ui;

}




void MainWindow::changeEvent(QEvent *e)
{
    QMainWindow::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}





 void MainWindow::displayMessage(){   //this method should  update the lineEdit (Xvaldisp)  the lineEdit however remains blank  but str gets updated


     ui->Xvaldisp->setText(str);

     str ="displayMessage hs rn";   //displaymessage has run

 }





    void MainWindow::on_Button_clicked(){ // this is a pushbutton(Button) that once pushed  also updates the same lineEdit(Xvaldisp)  this works just fine  If I clicked and released the mouse before on the GLWidget it would show the by displaymessage() updated string else it would be the orginal value   

        ui->Xvaldisp->setText(str);



    }
user2544191
  • 63
  • 1
  • 1
  • 5
  • 1
    Is mwd initialized. From your code it seems it is not. – Srikan Jul 02 '13 at 21:48
  • You need to pass the pointer to your existing MainWindow to the GLWidget – Frank Osterfeld Jul 02 '13 at 22:06
  • Thanks for the comments how would I be doing that? Really not familiar with cpp classes need to read up on it asap – user2544191 Jul 02 '13 at 22:47
  • You may have issues with initialization as described above... however you should also consider connecting a `signal` from the `GLWidget` to the `slot` in `MainWindow` rather than passing a pointer around. – tmpearce Jul 03 '13 at 01:20
  • possible duplicate of [Qt c++ GUI call from another class](http://stackoverflow.com/questions/17450039/qt-c-gui-call-from-another-class) – alexisdm Jul 03 '13 at 14:23
  • Well I figured out That the methow was getting called properly because it updates all variables except the ui – user2544191 Jul 06 '13 at 13:53
  • Same when I try with Signals and slots :/ I have no clue what to do anymore only thing I can imagine is updating the variables and then mùanually clicking a pushbutton to display them that works – user2544191 Jul 06 '13 at 14:34
  • Show more code... specifically the code where you initialize your MainWindow, and where you pass it to your widget. – tmpearce Jul 06 '13 at 21:05
  • @tmpearce Sounds like a good idea should've done that in the first place – user2544191 Jul 07 '13 at 13:01

1 Answers1

6

The root of your problem is that you seem to be misunderstanding the concept of pointers. Specifically, calling new is not the only way to obtain a pointer - a pointer is just a variable that holds the address of some object (or function). The new operator returns a pointer to a dynamically-allocated object, but there are other ways too, at least three of which are relevant to you:
1) Have someone else give you a pointer, for example as a function parameter;
2) Use & to take the address of an object.
3) Use this to get a pointer to the object you are currently working with.

Now that we have that out of the way, take a look at your code. MainWindow has two slots:

class MainWindow : public QMainWindow {
    Q_OBJECT
    ...
public slots:
   void on_Button_clicked();
   void displayMessage();

Slots are member functions - they are called on an object.

When you create an object of type MainWindow, the on_Button_clicked slot of your MainWindow object is automatically connected to the clicked signal of Button (via the meta-object compiler, a Qt-specific thing, because of the particular naming convention that you used).

What happens to the other one? Here's your code:

void GLWidget::mouseReleaseEvent(QMouseEvent *e){  
     MainWindow *mwd;  
     mwd=  new MainWindow;  
     QObject::connect(this, SIGNAL(valueCh()), mwd ,SLOT(displayMessage()) );  
     emit valueCh();  
     delete mwd;  
}

Rather than connecting to the slot of the original MainWindow object, you are creating a new object, calling its function, and promptly destroying it. So, while the slot does get called, it doesn't get called on the object that is actually your gui.

This is happening because you figured you needed a pointer to a MainWindow object, and used new to get one. The problem is, that pointer didn't point to the object you actually care about (i.e. your actual gui).

One (inelegant) solution is to not create a new MainWindow; instead, pass the address of the original MainWindow to the widget, and use that address (pointer) in the connect statement.

The much better solution is to skip all that stuff and use signals and slots the way they were intended, so that individual widgets don't have to know anything about the objects they are being connected to.

Change your MainWindow constructor to the following:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(ui->glWidget, SIGNAL(mouseReleaseEvent()),this,SLOT(displayMessage()));

}

and get rid of everything but the emit statement inside GLWidget::displayMessage.

tmpearce
  • 12,523
  • 4
  • 42
  • 60
  • Thanks I already suspected that I didn't get the address of my orginal MainWindow I still don't really understand the concept of OOP – user2544191 Jul 08 '13 at 17:25
  • It's a bit vague but maybe I'll get there in a few years I had to change a few things to get what you posted working but It now works great instead of ` connect(ui->glWidget, SIGNAL(mouseReleaseEvent()),this,SLOT(displayMessage()));` I used ` connect(ui->glWidget, SIGNAL(valueCh()),this,SLOT(displayMessage()));` and emit `valueCh();` Works great now and I'm happy :) – user2544191 Jul 08 '13 at 17:32