PDA

View Full Version : Saving Values from a Dialog to MainWindow - "cannot call member function w/o an objec



mbergmann-sh
20th February 2013, 07:36
Hi there! This is my first post to qt central. I'm stuck with my trials to save the contents of a Dialog in the calling MainWindow (MainWindow and Dialog created in QTcreator). The scenario: I have a MainWindow with a line edit, an integer spinbox and two buttons (one calls up the Dialog, the other one should call a public function that reads some private variables of class MainWindow and puts them into the line edit and the integer spinbox) and a Dialog with the same input Gadgets.
Plan was to write some public methods in class MainWindow that should have been used by class Dialog in order to store the values of the Dialog's input wigets in class MainWindow's private vars myTextString and myIntegerZahl.

Showing up the Dialog works, unless I call void setMyTextString(QString textstring); - in that case the program refuses to compile, throwing an error: "cannot call member function 'void MainWindow::setMyTextString(QString)' without object".

I did some reading on the Qt examples, but failed to find one that shows what I'm aiming at. Could somebody please show me the correct way of transfering the contents of my Dialog? Here comes the code:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "dialog.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void getMyTextString();
void setMyTextString(QString textstring);
void getMyIntegerZahl();
void setMyIntegerZahl();

private slots:
void on_btnDialog_clicked();
void on_btnUebertrag_clicked();

private:
Ui::MainWindow *ui;
Dialog *myDialog;
QString myTextString;
int myIntegerZahl;
};

#endif // MAINWINDOW_H

mainwindow.cpp

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

//#include "dialog.h"

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

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

void MainWindow::on_btnDialog_clicked()
{
myDialog = new Dialog;
myDialog->exec();
ui->le_myTextString->setEnabled(true);
}

void MainWindow::on_btnUebertrag_clicked()
{

}

// Austausch-Methoden
void MainWindow::setMyTextString(QString textstring)
{
myTextString = textstring;
}


dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include "ui_dialog.h"

//#include <QDialog>

namespace Ui {
class Dialog;
}

class Dialog : public QDialog, public Ui::Dialog
{
Q_OBJECT

public:
Dialog();

private slots:
void on_btnSend_clicked();

private:
Ui::Dialog *ui;
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"
#include "mainwindow.h"

Dialog::Dialog()
{
setupUi(this);
}

void Dialog::on_btnSend_clicked()
{
QString textstring = this->le_myTextString->text();
MainWindow::setMyTextString(textstring);
}

Any hints appreciated!

alrawab
20th February 2013, 07:53
use Qt emit signals to pass values from Dialog =>MainWindows
signalsandslots
http://www.digitalfanatics.org/projects/qt_tutorial/chapter02.html

Lykurg
20th February 2013, 08:14
Qt's Signal&Slot mechanism is great, but not for that task. Use simple getter and setter functions. As an simply -non compilable- example:
class Dialog {
QString getString() {return le_myTextString->text();}
};

myDialog = new Dialog;
myDialog->exec();
setMyTextString(myDialog->getString());


And you surely want to check what exec() returns.

alrawab
20th February 2013, 10:43
is implement of Q_PROPERTY valid in such case ?:)
http://www.developer.nokia.com/Community/Wiki/How_to_use_Q_PROPERTY

Lykurg
20th February 2013, 10:53
If the class inherit QObject you can also define Q_PROPERTY to inform the meta object about it, but no need to do so.

mbergmann-sh
20th February 2013, 13:22
use Qt emit signals to pass values from Dialog =>MainWindows
signalsandslots
http://www.digitalfanatics.org/projects/qt_tutorial/chapter02.html

Thanks for your answer and the links! Signal and slot was not what I indendet to do, since I've already s&s'ed the button of the Dialog - this calls the routine to write the values into the private MainWindow class variables. but I solved the Problem: I simply forgott to instantiate MainWindow! everything works fine after changing the slot to this:


#include "dialog.h"
#include "ui_dialog.h"
#include "mainwindow.h"

Dialog::Dialog()
{
setupUi(this);
}

void Dialog::on_btnSend_clicked()
{
MainWindow myMainWindow; // Wichtig: MainWindow instanzieren, sonst Compilerfehler!!!

QString textstring = this->le_myTextString->text();
myMainWindow.setMyTextString(textstring);
this->close();
}

Lykurg
20th February 2013, 14:17
Huh, no it is not important to initiate MainWindow. It is totally crap because myMainWindow is destroyed right after the function is left and has nothing in common with the instance of MainWindow you want to deal with. If you want access "MainWindow" from the dialog, you have to pass a pointer or emit a signal. There are no other possibilities if you want to change anything in MainWindow.

Further use QDialog::accept() instead of close.

mbergmann-sh
20th February 2013, 14:22
Ha! Triumphed too early...
now it compiles fine, but since I instantiated MainWindow within void Dialog::on_btnSend_clicked(), it seems that it dies after leaving the Function without writing to MainWindow's private variables.
Debugging the Function in Dialog returns exactly the values entered, debugging the MainWindow's variables show them empty. I must be totally blind, but I don't see what's going wrong here.
QString myTextString within Dialog: "Blabberdiblub"
QString myTextString within MainWindow: ""
int myIntegerzahl in Dialog: 11
int myIntegerzahl in Mainwindow: 2 (seems to be a value-by-chance).

I'm confused...

These are my Methods in mainwindow.cpp:


// Austausch-Methoden
void MainWindow::setMyTextString(QString textstring)
{
myTextString = textstring;
qDebug() << myTextString;
}

QString MainWindow::getMyTextString()
{
return myTextString;
}

void MainWindow::setMyIntegerZahl(int integerzahl)
{
myIntegerZahl = integerzahl;
qDebug() << "myInt: " << myIntegerZahl << ", Int: " << integerzahl;
}

int MainWindow::getMyIntegerZahl()
{
return myIntegerZahl;
}


...and this is how I call them in my Dialog:


void Dialog::on_btnSend_clicked()
{
MainWindow myMainWindow; // Wichtig: MainWindow instanzieren, sonst Compilerfehler!!!

QString textstring = this->le_myTextString->text();
myMainWindow.setMyTextString(textstring);
myMainWindow.setMyIntegerZahl(this->spb_myIntegerZahl->value());

this->close();
}

...at last, this is my class definitions for MainWindow:


#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "dialog.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QString getMyTextString();
void setMyTextString(QString textstring);
int getMyIntegerZahl();
void setMyIntegerZahl(int integerzahl);

private slots:
void on_btnDialog_clicked();
void on_btnUebertrag_clicked();

private:
Ui::MainWindow *ui;
Dialog *myDialog;
QString myTextString; // Ablage für Text aus dem Dialog
int myIntegerZahl; // Ablage für Integer aus dem Dialog
};

#endif // MAINWINDOW_H



aahh - sorry Lykurg, I didn't see you have already pointed to that failure. I'll give it a thought and try to rewrite that crap! ;)

Lykurg
20th February 2013, 14:38
Hi that is basic OOP!
In Dialog::on_btnSend_clicked() you create a *new* instance of MainWindow which has no connect with the instance of MainWindow from which you execute the dialog. Again define getter functions in the dialog, and after the dialog is finished use them to alter the MainWindow. Have a second look at my example.

mbergmann-sh
20th February 2013, 14:52
didn't see you had already pointed to that failure. I'll give it a thought and try to rewrite that crap after overlooking your example. Thanks a lot!

wysota
20th February 2013, 15:13
I don't know what your dialog is supposed to be used and what its relation to MainWindow is but if what Lykurg suggested is somehow not an option for you (although it is the best solution possible), another solution would be to pass a pointer to MainWindow to the dialog. However, again, from OOP perspective, it is better to query a value from the dialog and set it on the main window from outside of the dialog.

mbergmann-sh
20th February 2013, 15:54
I'm writing on a small alarm watch app consisting of a main window showing times and allowing to start a predefined alarm time, and some user dialogs fpr setting up different alarm tunes (as mp3) and entering events to be shown on wake time. This so far is what I'm working on. Since I need to store the values of those Dialogs in the main window, I thought it as a good idea soing this in the MainWindow class private vars. I wanted to have them central, because of the need of writing them into a presets file and because they are njeeded by the main window in order to do its job. The example code above, however, is a simplified rewrite mirroring my problem - not the app I'm working on. Since I'm relatively new to C++ I expect more quirks and quarks to come there... ;)

I worked myself through a German book titled "C++ in 21 Tagen", also through "The independant Qt tutorial" and the Blanchette Book on Qt, and I have some knowledge in C from my Amiga times. :)
Nevertheless, i see there's more needed to fully understand C++'ing with Qt. Some concepts still confuse me, since I'm still thinking in more procedural terms. Once after a while I hope it'll change to more OOP thinking, but I have to get used to it. Guess there's more practice to be done...
I'll start giving it a try with both possibilities in some test projects: handing a pointer to MainWindow and using getter functions. The last was what I thought I did, but obviously they are needed in the Dialog - and I implemented them in MainWindow.

Thanks a lot for all your hints! This seems to be a very friendly forum.