Are "Stacked Widgets" and "Building GUI's using inheritance" mutually exclusive?
-
I am just starting out in -QT- Qt and was considering building GUIs bit-by-bit using inheritance. That is, the base class would create common widgets, the next class would inherit those widgets and adds more widgets and so on. This makes perfectly good sense to me. Then along comes Stacked Widgets. Here it makes more sense to create all your widgets at once. For all of your screens. That doesn't fit well into C++ inheritance. Further if you force your self to use Stacked Widgets while using inheritance the Stacked Widget advantages tend to disappear. For example, you would only create the widgets needed for a particular inheritance lineage. So, at the end of that lineage, the object that is created would have a number of nested Stack Widgets all of which only have one layer of widgets (i.e. they all only have a index range of 1). Kind of pointless.
Am I thinking of Stacked Widgets wrong? Do people use Stacked Widgets and inheritance at the same time.
-thanks for any help
edit: please write Qt, not QT. QT is QuickTime; Andre
-
They way you imagine constructing GUI's is not how people usually work with them. In practice, often it does not make that much sense to use inheritance in the way you describe, though it can work in some instances. Usually, people use composition and encapsulation instead. That is: a GUI is a compostion of several existing widgets, and the main window itself uses inheritance from a sensible base class (QDialog, QMainWindow, or something else). Stacked widgets may have a place in such GUI's, but they are not used all that often. They are use to create UI's in which you have pages of different items that the user can somehow switch out; or to show different widgets depending on the state of some other widget(s). That may be what you need, but you don't use it all that often.
So, there is a place, time and usecase for all of the techniques mentioned: inheritance, encapsulation and stacked widgets.
-
Hi...
Thank you both for following up on my post.
As with anything new there seems to be too many options. I'd like to find the best before proceeding to far into this project. I appreciate everyone's help.
Andre, usually "composition" (and aggregation) examples involve variables. Can you point me to a Qt example where composition is used to assemble groups of widgets onto a screen? Again, my objective is to avoid the redundant programming of groups of widgets which happen to be common between similar Qt screens.
It appears another approach is to use Qt's "Layout Management". Layout management's primary purposes sounds like fitting a child widget into a parent widget's space. But the notion of having child and parent widgets sound exactly what is needed when creating multiple screens with redundant groups of widgets as described above.
-thanks
-
Basically, any Qt demo and example will be a good example for the composition approach. If you design a form using Designer and add it to your project, you'll notice that a _ui.h file will be generated for it. If you open it up, you'll find the declarations for the variables representing all the widgets on the form. You can do the same manually.
Qts layout management capabilities are not yet another approach here. It is orthogonal to the other approaches (to a certain extend, anyway). While the inheritence vs composition has to do with the object structure (who owns who, what is what, etc.), layout management is concerned with the positions and sizes of the different widgets on a parent widget. An example:
Say you wish to create a user interface element that you want to reuse, for instance a file selector widget. It consists of a grouping of a QLineEdit and a QToolButton next to it, where the line edit will contain the file name that was entered or selected, and the tool button allows you to select a file name using a QFileDialog.
Your first question needs to be what this widget is: is it a line edit, and should it thus have the same interface as one? Or is it another widget that needs an interface of its own, and only contains a line edit? In this case, the second case it best. It is not all that relevant for the functioning of the widget if it really is a line edit or not; it might as well be an (editable) combo box that also supplies a list of recently used files.
Our file selector thus needs to inherit only the most basic of widget classes: QWidget. Anything more specialized would only confuse the users of the widget, and constrain us in the implementation of it. So, we inherit QWidget, because our FileSelector is a widget.
FileSelector needs to show two components: a QLineEdit, and a QToolButton. So, we use composition to do that. We give the FileSelector class two private member variables to point to these widgets, and construct them as children of this in the constructor. That means we end up with FileSelector being inherited from QWidget, and then also being a composition of a QLineEdit and a QToolButton which both have a child-parent relation with the FileSelector component. (Because of the parent-child relationship, you end up with two pointers to the child widgets: one via QObject's interface, and one via the member variables you created. You could skip the direct member variables, but I would not recommend that, as it will only make your life harder.)
Now, if you would make your widget appear on screen (any widget can become a top level one, so that would be easy), you would notice that although a line edit and a button appear, they are not in the right postion to each other. You want to button to appear to the right of the line edit. To do that, you use a QLayout. A layout manages the sizes and positions of child widgets for a parent widget. FileSelector is a QWidget, and so are the button and line edit child widgets, so our situation matches the use case of a layout. In this case, a simple QHBoxLayout will suffice, but for more complicated situations or complete forms you may need to use other layouts and/or a combination of different layouts.
So, in just our FileSelector widget, we have used all three: inheritance from QWidget, composition of QLineEdit and QToolButton within FileSelector, and a layout to manage the sizes and positions of these.
Of course, now you'll need to design an API for the FileSelector so you can sensibly get and set file names, set selection modes, get notification of changes, etc. And, of course, you'll need to implement the code to react to clicks on the button to actually show your QFileDialog and to send out the appropriate signal if the file name has changed via a selection or via direct editing. I'll leave that as an excersise for the reader ;-)
Note that if you want to use this FileSelector in a bigger form, you'd again use compostition of this FileSelector to form a part of a bigger whole, and perhaps this time you would use a QDialog as your base class for the inheritance instead of QWidget.
-
Hi folks,
I have a [hopefully] more specific topic/example to address re: GUI creation/architecture.
DISCLAIMER: I am both relatively new to Qt AND a procedural rather than OO programmer at heart
Let's say my app will use a stacked widget made up four pages (0-3). For the sake of discussion...
Page 0 = full screen video
Page 1 = partial screen video with a text box underneath
Page 2 = grid of buttons
Page 3 = small video + image + text boxFurther, pages 2 & 3 both share/use some common elements, let's call them Label1, Label2, Button1, Button2
Each page's widget as well as the common content are in their own class.
My top level GUI class instantiates the common class and passes that pointer to the constructors of the classes for pages 2 & 3.
My challenge right now is the parent-child relationships formed by assigning widgets to layouts or layouts to layouts. For the example described, the common elements Label1, Label2, Button1 and Button2 will be placed the same on page 2 and on page 3. I rashly assumed that I could add these widgets or their layout from the common class to the layout managers on the pages that use them but this seems to not work.
If any of this makes sense, any practical advice would be most appreciated !
Regards,
John