PDA

View Full Version : How to get a reference for a control of the main form?



thiforums
20th March 2009, 04:06
Using the QT Designer I have made the following things:
1-a main form called MainFormDlg (QMainWindow) with a Tree Widget control (treeDownloads);
2-a dialog box called DownloadDlg (QDialog) containing OK and CANCEL buttons.

When the user presses the OK button in the DownloadDlg dialog, I wanna clear the content of the treeDownloads. But I don't know how to get a reference to treeDownloads which is from the main form.

My code below compiles fine, but when I press the OK button on the DownloadDlg dialog, the program simply crashes. (Please, look at my questions at the commented lines **):

//downloaddlg.cpp:


#include "downloaddlg.h"

DownloadDlg::DownloadDlg(QWidget *parent) :
QDialog(parent){
setupUi(this);

connect(buttonBox, SIGNAL(accepted()), this, SLOT(addUrlsToTree()));

setAttribute(Qt::WA_DeleteOnClose);
pMainForm = (Ui_MainFormDlg*)parent; // ** Is this correct? **
}

void DownloadDlg::addUrlsToTree(){
pMainForm->treeDownloads->clear(); // ** Is this correct? **
}


//downloaddlg.h:


#ifndef DOWNLOADDLG_H
#define DOWNLOADDLG_H

#include <QtGui/QDialog>
#include <QtGui/QMainWindow>
#include "ui_downloaddlg.h"
#include "ui_mainform.h"
//#include "mainform.h"

class DownloadDlg : public QDialog, private Ui::DownloadDlg {
Q_OBJECT
Q_DISABLE_COPY(DownloadDlg)
public:
explicit DownloadDlg(QWidget *parent = 0);

private:
Ui_MainFormDlg *pMainForm;

private slots:
void addUrlsToTree();

protected:
virtual void changeEvent(QEvent *e);
};

#endif // DOWNLOADDLG_H

talk2amulya
20th March 2009, 05:15
what is the significance of this:


pMainForm = (Ui_MainFormDlg*)parent

i believe what u are trying to do(or should do) is


this->setParent(pMainForm)

my guess is with your statement, pMainForm is getting a NULL value, which causes the crash when u try to access that variable in addUrlsToTree().

thiforums
20th March 2009, 05:52
what is the significance of this:


pMainForm = (Ui_MainFormDlg*)parent

I thought that the 'parent' argument of DownloadDlg constructor was a reference to the parent window (in this case to the MainFormDlg). But I hope it's wrong.



i believe what u are trying to do(or should do) is

this->setParent(pMainForm)

my guess is with your statement, pMainForm is getting a NULL value, which causes the crash when u try to access that variable in addUrlsToTree().

I tested the instruction you passed, it compiles, but when I try to create the DownloadDlg the app crashes. :(

//downloaddlg.cpp


DownloadDlg::DownloadDlg(QWidget *parent) :
QDialog(parent){
setupUi(this);
connect(buttonBox, SIGNAL(accepted()), this, SLOT(addUrlsToTree()));
setAttribute(Qt::WA_DeleteOnClose);
this->setParent((QWidget*)pMainForm); //** problem here, only way I found to compile it **
}


I'm creating the dialog using this code:

//mainform.cpp


void MainForm::newDownloadDlg(){
DownloadDlg *dlg=new DownloadDlg(this);
if(dlg->exec()){
//ok pressed
}
}


I'm not sure if you understood what I need, but I just wanna have access to the treeDownloads control through DownloadDlg dialog, then I'll be able to play with this control (like adding,clearing,deleting items etc)

talk2amulya
20th March 2009, 05:56
when using this:


DownloadDlg *dlg=new DownloadDlg(this);

u wont need to call setParent as i told, cuz the above statement will achieve that functionality..so remove the setParent() call and run again

thiforums
20th March 2009, 06:16
If I remove that line, the code will come back to the start and nothing changes.

Look below the code. I'm trying to access the treeDownloads control (which is located at the MainFormDlg class) through DownloadDlg class. But doing that way occurs an error:


void DownloadDlg::addUrlsToTree(){
treeDownloads->clear(); // ** error: "treeDownloads was not declared on this scope **
}

I wanna know how can I avoid this error.

faldzip
20th March 2009, 07:39
(First of all - read this post to the end, although it's so long :])

Try this way:


#ifndef DOWNLOADDLG_H
#define DOWNLOADDLG_H

#include <QtGui/QDialog>
#include <QtGui/QMainWindow>
#include "ui_downloaddlg.h"
#include "ui_mainform.h"
//#include "mainform.h"

class MainFormDlg; // let DownloadDlg know about MainFormDlg without includeing file here

class DownloadDlg : public QDialog, private Ui::DownloadDlg {
Q_OBJECT
Q_DISABLE_COPY(DownloadDlg)
public:
explicit DownloadDlg(MainFormDlg*parent = 0); // change QWidget to MainFormDlg as you this would be the parent for sure

private:
MainFormDlg *pMainForm; // don use the UI_, just make one more method in MainFormDlg (see below)

private slots:
void addUrlsToTree();

protected:
virtual void changeEvent(QEvent *e);
};

#endif // DOWNLOADDLG_H


And then:


#include "downloaddlg.h"
#include "mainform.h" // the file with MainFormDlg

DownloadDlg::DownloadDlg(MainFormDlg*parent) :
QDialog(parent),
pMainForm(parent) // pMainForm points to the parent = MainFormDlg
{
setupUi(this);

connect(buttonBox, SIGNAL(accepted()), this, SLOT(addUrlsToTree()));

setAttribute(Qt::WA_DeleteOnClose);
}

void DownloadDlg::addUrlsToTree(){
// but to get to the ui parts you have make them public or make some other methods
}


For example you can do:


public:
Ui::MainFormDlg * ui;

in MainFormDlg class, or make some public method like void clearTree(); which will clear the tree.

But this is the way you want to do and it's not good i think. I think the better way is to use signals and slots. I dont know what the buttonBox is in your dialog, but if the signal is emitted outside the DownloadDlg you can just connect accepted() to the clear() slot of the tree in MainFormDlg just below the DownloadDlg creation. If it's not possible to get the signal accepted() in MainFormDlg, make your own signal like acceptedSignal() and connect it to clear(). Example:


#ifndef DOWNLOADDLG_H
#define DOWNLOADDLG_H

#include <QtGui/QDialog>
#include <QtGui/QMainWindow>
#include "ui_downloaddlg.h"
#include "ui_mainform.h"

class DownloadDlg : public QDialog, private Ui::DownloadDlg {
Q_OBJECT
Q_DISABLE_COPY(DownloadDlg)
public:
explicit DownloadDlg(QWidget *parent = 0);

signals:
void acceptedSignal();

protected:
virtual void changeEvent(QEvent *e);
};

#endif // DOWNLOADDLG_H



#include "downloaddlg.h"

DownloadDlg::DownloadDlg(QWidget *parent) :
QDialog(parent){
setupUi(this);

connect(buttonBox, SIGNAL(accepted()), this, SIGNAL(acceptedSignal())); // first signal emits second one

setAttribute(Qt::WA_DeleteOnClose);
}


and in MainFormDlg:


void MainForm::newDownloadDlg(){
DownloadDlg *dlg=new DownloadDlg(this);
connect(dlg, SIGNAL(acceptedSignal()), ui->treeDownloads, SLOT(clear())); // connects accepted with clear, and that's what you want, right?
if(dlg->exec()){
//ok pressed
}
}


That is better way i think :] good luck! :]

thiforums
20th March 2009, 17:20
faldzip, thank you very much, your code was very useful for me to get my program working.
About your sugestion, using signals/slots, I'm still a begginer on qt framework and I was just trying to do a simple task which was to have access to a UI control through another dialog.

In main form I'm able to access the UI control directly, for example:

MainForm::MainForm(QWidget *parent)
: QMainWindow(parent)
{
setupUi(this);
createActions();
createToolBars();

treeDownloads->clear(); // ** direct access to the tree widget control **
}
I'm not sure but I think this works because I used Multiple Inheritance concept when declaring MainForm as public of Ui_MainFormDlg.

Then, inside the DownloadDlg class I was trying to do something similar, like this:
void DownloadDlg::addUrlsToTree(){
pMainForm->treeDownloads->clear();
}
I'm more confortable using this way than creating many methods to do something with the tree widget.

Bye