PDA

View Full Version : Model/View/MainWindow



qtnewbie500
30th May 2012, 21:05
I have a question about style... I am writing an application where my view is a View class derived from QGLWidget, and is initialized with the Model class and the parent widget, which in this case will be a QMainWindow, or a class derived from it. I used to have this in my main:

QMainWindow* mainWin = new QMainWindow();
Model model;
View view(model, mainWindow);

mainWin->setCentralWidget(&view);

Everything was working fine, but I decided that I need to subclass QMainWindow and make it an app specific MainWindow, as I suspect I should have done since the beginning... the problem now is where do I create and how do I hook up the model and the view to the MainWindow? I tried this:

MainWindow::MainWindow(){
Model* model = new Model();
View* view = new View(*model, this);
...

}

The problem is, I feel nervous about sending "this" to the View's constructor, even if it works now I feel this should lead to problems in the future... As I am new to QT, I would appreciate anyone telling me what is the correct way/style to accomplish this...

Thanks a lot!

sedi
31st May 2012, 01:22
Hi,
I am not a guru at all but I'll give my 2ct. HTH:

I can't see anything wrong in providing "this" as a parent's reference: for me it seems the most normal thing to do - I do that all the time. You create a child and give it a pointer to its parent.
It also seems right for me, to make model and view members of MainWindow, for MainWindow is normally the place where all the "strings" are being connected and pulled. You need a place where you can "see" the important children and connect their signals and slots.
As you've stated: to subclass QMainWindow is - according to my knowledge - a good and apparently the most common way to write a program.

Experts, gurus, gods: please correct me, where I'm wrong!

qtnewbie500
31st May 2012, 18:32
The problem here is that I'm sending "this" from inside the class constructor... this is generally bad practice because depending on what the function you're sending "this" to does, the object might not be fully constructed yet and the whole thing can crash...




I can't see anything wrong in providing "this" as a parent's reference: for me it seems the most normal thing to do - I do that all the time. You create a child and give it a pointer to its parent.

Experts, gurus, gods: please correct me, where I'm wrong!

d_stranz
31st May 2012, 20:31
The problem here is that I'm sending "this" from inside the class constructor... this is generally bad practice because depending on what the function you're sending "this" to does, the object might not be fully constructed yet and the whole thing can crash...

By the time you get to the part in your constructor where you are building child widgets and adding them to your MainWindow GUI, the class is as constructed as it needs to be. The important part as far as adding child widgets is concerned is that the QMainWindow base class has been constructed, and that's been done as soon as the initialization part of the constructor is finished (i.e. the : QMainWindow( parent ) bit in the initialization list).

If you think about it, what you want to do is no different from what the setupUI( this ) call is doing in a constructor where the GUI is generated using Qt Designer.

By the way, it is *almost always* an error to create a QWidget instance on the stack and pass it in as "&widget" as you did in your first post in the thread:


QMainWindow* mainWin = new QMainWindow();
Model model;
View view(model, mainWindow);

mainWin->setCentralWidget(&view);


In this case, it works because the View instance stays in scope for the duration of main(). However, when you set the parent of a widget (as mainWin->setCentralWidget() does), the parent widget takes ownership of the lifetime of that child and will delete it when it is itself deleted. In your original code, the View instance is created on the stack, which means when you delete the mainWin instance, it will try to delete a stack variable and probably crash your program.

If you are going to do things on the stack in main(), the preferred way is this:



QApplication app;
QMainWindow mainWin;
Model model;
View * view = new View( model, 0 ); // assuming your View constructor doesn't default "parent" to 0
mainWin.setCentralWidget( view );

app.exec();


This reverses the stack / heap allocation you used. Here, it is perfectly OK to allocate mainWin on the stack, and when it goes out of scope at the end of main(), it will correctly delete the View pointer it holds as a child.

By the way, when you post code, please use [CODE] tags. You can insert them by clicking the "#" icon in advanced editing mode, then type or paste your source code inside them.