tags:

views:

62

answers:

4

I'm looking for a way to specialize a widget at runtime. I have a form created with Qt Designer. In this form there is a widget that displays user data, like name, age and so on. Then the user chooses a file and according to the type the widget shall display additional information (like to OO example person -> student, teacher).

I tried to put an empty QWidget on my form, assigned a person widget to it and if the user clicks a button I call deleteLater() on person and assign a new Student(). This works but the new widget then doesn't follow the layout.

I also found QStackedWidget. This seems to work but because all possible widgets are created when the form is shown, even if they are never used, this way doesn't feel right.

What would be the way to accomplish this?

Edit: I feel that my question is a bit unclear. What Qt mechanism should be utilized if one wants to replace a QWidget with a specialized (inherited) version of the original widget? I'm looking for the Qt way to do this.

A: 

Maybe the problem is not that the widget is not suitable, but simply that you're not giving time for the widget to update.

You could take a look at processEvents: http://web.mit.edu/qt-dynamic/www/qapplication.html#details

Baltasarq
I'm sorry, I don't understand what you mean. At the moment there are no event in place (I didn't put any in), just a click of a button in an example app. The new widget is shown after a call of myWidget->show(), but it's not display where the original widget used to be. Instead it's in the left upper corner. Did I get something wrong?
DaClown
A click in a button is an event. Any operation the user does is translated to an event. If you are inside a loop in one of your application event handlers, the Qt library will not be able to update the status of the GUI. That's when processEvents() is useful.
Baltasarq
A: 

This looks like a use case for the factory pattern.

#include <map>
#include <string>
struct Whatever;
struct QWidget;
typedef QWidget*(*WidgetCtor)(Whatever*);
typedef std::map<std::string, WidgetCtor> FileFactory;

QWidget* createFoo(Whatever*);
QWidget* createBar(Whatever*);
QWidget* createDefault(Whatever*);

void factory_init(FileFactory& ff)
{
    ff["foo"] = createFoo;
    ff["bar"] = createBar;
}

QWidget* create_by_factory(const FileFactory& ff, const std::string t, Whatever* w)
{
    FileFactory::const_iterator it(ff.find(t));
    if(it != ff.end())
    {
        return it->second(w);
    }
    else
    {
        return createDefault(w);
    }
}
Rudi
Thanks for your reply. A factory would be helpful if I have to generate those objects more often. But in this case a factory seems a bit of an overkill.
DaClown
A: 

Adding widgets dynamically to a layout is not a problem. You might need to call updateGeometry on the containing widget though.

Frank
UpdateGeometry didn't work. It's not quiet adding a widget, it's more replacing an existing widget in a layout with another widget.
DaClown
replacing should be the same as adding a new widget. did you call updateGeometry() on the correct widget, i.e. the one with the layout where you inserted the new widget?
Frank
+1  A: 

You need to add a widget dynamically to the widget you have drawn in the designer.

// in UI file
QWidget *wdgFromForm;

// in cpp file 
QHBoxLayout *const layout(new QHBoxLayout(wdgFromForm)); 
SpecializedWidget * specializedWidget( new SpecializedWidget(wdgFromForm));
layout->addWidget(specializedWidget);
TimW
Thanks, this works. Is this the way it is done in Qt? I find it a bit odd that instead of replacing an already existing widget that is float in an existing layout, I have to add a layout to this widget and put the new widget in this new layout.
DaClown
You could setup the entire form dynamically, but I find it easier to setup the form with the designer an use a placeholder for the context dependent widgets.
TimW
Exactly this was my intention. As I said, I just find it odd that I have to add a layout and then add a new widget instead of just replacing the placeholder. But anyway, I like it more than the QStackedWidget approach. Thanks.
DaClown