Converting a QFrame to a QWidget

I had spent the better part of yesterday building, integrating, and testing a Qt form that was a single panel on a larger display. This morning I was tasked to “make it a popup” instead.

The back-end to the GUI was a C++ class that inherited a custom SubFrame object, which inherits Qt’s QFrame object. My company also has a custom Popup class. Very similar to SubFrame, the Popup class, notably, inherits instead from a QWidget.

I made the appropriate edits to my source code so that MyFormThing inherited Popup instead of SubFrame. It didn’t build, though. The setupUi() method in the Qt-generated Ui file expected a QFrame * input parameter, but from MyFormThing I was passing this to the method—this now being a QWidget *. My GUI, as far as the .ui file went, was still a QFrame. It needed to be a QWidget.

Simply casting the QWidget to a QFrame won’t work, since a QWidget is a not a QFrame. This:

ui->setupUi(dynamic_cast<QFrame *>(this));

will build, but it will not run very far—the messed up dynamic cast throws an exception and a core dump is born.

I knew I needed to change the .ui file, somehow, to make my QFrame a QWidget. Qt Creator doesn’t, AFAIK, give the ability to do this kind of morph—at least not in version 1.3.1, which is what’s installed on our lab computers. And obviously I wasn’t going to rebuild the whole thing from scratch starting with a QWidget base. Some quick Googling led me here.

The .ui files in Qt are just XML. Near the top of the MyFormThing.ui file, I found this:

<widget class="QFrame" name="MyFormThing">
<property name="frameShape">
    <enum>QFrame::WinPanel</enum>
</property>
<property name="frameShadow">
   <enum>QFrame::Raised</enum>
</property>

So I changed class="QFrame" to class="QWidget", deleted the frame-specific properties, and rebuilt/ran without issue. When I inspected the GUI element in Qt Creator’s Form Designer, it said it was a QWidget, so it looks like that worked.

tl;dr Change a QFrame into a QWidget by directly editing the XML in the .ui files.