PDA

View Full Version : Dynamically Loading a QMainWindow?



natron
19th July 2006, 19:48
First, to describe my setup, I'm using Qt 4.1 patched in with VS2005 on Windows XP.

I've been using Qt for a couple day now, and have managed to run into troubles early.
I'm trying to dynamically load my Qt Designer-created QMainWindow, much like the Calculator Builder (http://doc.trolltech.com/4.1/designer-calculatorbuilder.html) example does with a QWidget. I can compile and use the calculator perfectly.
I figure changing the parent class and a couple ctor items should work for a QMainWindow...right?

Here's essentially what I'm working with:



class MainForm : public QMainWindow
{
public:
MainForm(QMainWindow *parent = 0);
}




MainForm::MainForm(QMainWindow *parent) : QMainWindow(parent)
{
QUiLoader loader;
QFile file(":/forms/mainwindowgui.ui");
file.open(QFile::ReadOnly);
QWidget *formWidget = loader.load(&file, this);
file.close();

QLayout *layout = new QVBoxLayout;
layout->addWidget(formWidget);
setLayout(layout);
}


And the main.cpp remains the same as the calculatorbuilder example.

This seems simple, but clearly I'm missing something crucial. Any input is appreciated. Thanks.

wysota
19th July 2006, 20:15
Are you sure you added the /forms/mainwindow.ui file to your resources system (and that it is accessible under that name)?

natron
19th July 2006, 20:28
Yes on both.

Here's what my mainwindowbuilder.qrc file looks like


<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/forms">
<file>mainwindowgui.ui</file>
</qresource>
</RCC>


and I might as well reveal my main.cpp:


int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Q_INIT_RESOURCE(mainwindowbuilder);
MainForm winMain;
winMain.show();
return app.exec();
}


I've verified the file being loaded by simply adding a
formwidget->show()
in my class file, and the form does work. However, not actually being associated with the class yet, it doesn't have any use.

jacek
19th July 2006, 21:10
MainForm::MainForm(QMainWindow *parent) : QMainWindow(parent)
{
QUiLoader loader;
QFile file(":/forms/mainwindowgui.ui");
file.open(QFile::ReadOnly);
QWidget *formWidget = loader.load(&file, this);
file.close();

QLayout *layout = new QVBoxLayout;
layout->addWidget(formWidget);
setLayout(layout);
}

You should use QMainWindow::setCentralWidget() instead the layout, since main windows have their own layout.

What widget is mainwindowgui.ui based on? QMainWindow or QWidget?

natron
19th July 2006, 22:01
I changed the layout jargon to setCentralWidget. Unfortunately, that didn't make a difference.

I created the form by choosing "Main Window" from the New Form dialog in Qt Designer. If that decides what its "based on", then QMainWindow is it.

jacek
19th July 2006, 22:11
I created the form by choosing "Main Window" from the New Form dialog in Qt Designer. If that decides what its "based on", then QMainWindow is it.
This might be the problem, you are trying to put a QMainWindow inside QMainWindow.

natron
19th July 2006, 22:47
Good point.

I changed the parent class to QWidget, but like my story goes, it still doesn't work.

Since this is no longer a QMainWindow subclass, the setCentralWidget is no longer available. With or without the original layout code, my GUI isn't showing up. One noted difference though, the blank form that shows up with the layout code is small, slightly larger than the window decroations. Removing the layout code creates a huge window that feels close to a main window...I swear the solution must be near.

As a side, how do you experts start your Qt applications? This seems like a natural way to do it; it's similar to how I've done this type of thing in Gtk.

jacek
19th July 2006, 23:18
Since this is no longer a QMainWindow subclass, the setCentralWidget is no longer available.
This time you try to put QMainWindow on QWidget.

As you can see:

QMainWindow::QMainWindow(QWidget *parent, Qt::WFlags flags)
: QWidget(*(new QMainWindowPrivate()), parent, flags | Qt::Window /* <- note this flag */ )
{
d_func()->init();
}
QMainWindow is always a top level window. You have to either change your .ui file or use a different approach.


As a side, how do you experts start your Qt applications?
I prefer to use uic instead of QUiLoader. If you store .ui files in resources it doesn't make much difference, except that the code generated by uic is smaller and runs faster.

wysota
19th July 2006, 23:24
Since this is no longer a QMainWindow subclass, the setCentralWidget is no longer available.
Maybe you should create an instance of QMainWindow and then use setCentralWidget to set your widget as its main part? I mean something like:


int main(int argc, char **argv){
QApplication app(argc, argv);
// ...
QMainWindow mw;
mw.setCentralWidget(createYourWidgetHere);
//...
mw.show();
return app.exec();
}



As a side, how do you experts start your Qt applications?
I don't exactly understand what you mean... How do we execute applications or how do we implement them?

If the former then either from the command line, KDevelop or by clicking on an icon in Konqueror. I think all people do it in one of these ways...

If the latter, then I start by writing main.cpp with contents such as the one above, then implement my main ui, subclass it to create the main window class and then I check if it works fine. Afterwards I begin to implement the functionality.

And I don't use dynamically loaded forms :)

natron
20th July 2006, 19:24
Hey, thanks you two for your help. I got it working so far.

I realized my blunder - I basically had the right code, just in the wrong place.

My main now loads the .ui file, followed by


MainForm mfMain;
mfMain.setCentralWidget(formWidget);


where the ctor for MainForm goes like so


MainForm::MainForm(QWidget *parent) : QMainWindow(parent)
{
//...
}


This makes a lot of sense too; it works like wysota's post above.

Any idea why Gtk's (using Glade) method of interface design explicitly promotes dynamic interface loading, while in Qt land the paradigm focuses on the static method? I can see advantages and restrictions in both, but neither seems clearly better.

wysota
21st July 2006, 01:15
Any idea why Gtk's (using Glade) method of interface design explicitly promotes dynamic interface loading, while in Qt land the paradigm focuses on the static method? I can see advantages and restrictions in both, but neither seems clearly better.

<flame mode>
Maybe because Qt is better?
</flame mode>

Qt is object oriented and focuses on using classes, also for things like the GUI, whereas Gtk is not object oriented and doesn't care about classes, so it doesn't matter where it creates its bunch of variables responsible for controlling the user interface. Of course that's my personal opinion :)