Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Design

The Qt Designer IDE


September, 2004: The Qt Designer IDE

Everything but the compiler

Dave is a professional programmer responsible for the original design of the Qt SQL database layer. He can be contacted at moseyfreeshell.org.


Among the many GUI programming libraries available, both free and licensed, the Qt C++ Library from Trolltech (http://www.trolltech.com/) has a strong following. And with the advent of Qt Designer 3.3.1, Qt developers now have a feature-rich IDE with which to design and code GUI applications. The lack of compiler support is the only significant drawback in an otherwise polished and useful tool.

The original Qt Designer that appeared in Qt 2.0 did one thing, and did it well—WYSIWYG interface design. This filled a void in the world of Qt development, which at the time, required most of this code be hand written. The Designer in Qt 3.3.1 goes beyond simple GUI building, supporting full project management, source-code editing, resource management for images and database connections, and a full suite of design controls.

Designer produces tight, reliable code, and does so for all platforms supported by Qt—Windows, Linux and other UNIX platforms, and Mac OS X. Because Qt is a C++ library, all code produced by Designer is in C++. To support the advanced event handling of Qt, there are some additional preprocessing steps necessary when compiling applications based on Qt. This may seem like unwanted overhead but, in practice, these steps are integrated neatly into the compilation process, and you are rarely bothered by any of the details.

Designer works with Qt project files (.pro) directly so that it can be used on an as-needed basis to design and implement the GUI portions of your application, and it does so in a straightforward and understandable way. Designer's project management gives you control over application include paths, linking with other libraries, and platform-specific settings; see Figure 1.

Designing

The original method for designing user interfaces is still available in Designer 3.3.1, and is often the fastest and most straightforward way of using Designer in C++ GUI projects. To fully appreciate what is going on while designing interfaces, an understanding of the Qt object model is necessary.

In Qt, all classes inherit from QObject and all visual classes inherit from QWidget. QObject provides the framework for interobject communication and also provides memory management for child objects. QWidget (which is derived from QObject) provides event handling, painting routines, and window functionality. Designer exploits the metainformation available in the Qt object system and, through limited introspection, can make the method names and parameters of Qt classes available to designers. Interfaces are saved in .ui files that are preprocessed by a User Interface Compiler (uic) during compilation. The uic generates regular C++ classes that correspond to the interface you designed. You can extend the behavior of these generated classes by inheriting from them normally. An Address Book application (Version 1 is available electronically; see "Resource Center," page 5) uses this method of design. The Address Book application displays a list of contacts, and lets you alter and insert contact information using QLineEdit widgets.

The latest Designer improves upon this basic method of design by now providing integrated source-code editing of your interfaces, which avoids the extra step of inheriting from Designer-generated classes and significantly speeds up development time.

The actual process of building interfaces in Designer is what you would expect from a modern IDE, and Designer supports all widgets provided by Qt (Figure 2). One interesting feature is the automatic layout tools that let you drop a bunch of controls onto a window, then be able to quickly organize and manage layouts with a minimum of fuss (Figure 3). In addition, widget properties can be edited in groups with the property editor after selecting them in Designer (Figure 4).

If you're familiar with modern GUI builders, you will be comfortable using Designer to build interfaces. You can select different widget types and place them on your windows, grouping and organizing them in any way. You can also set widget properties, define tool tips, adjust layouts, initialize list boxes, and so on. There are a few annoyances, including the lack of a default action when placing new widgets—pressing Enter usually does nothing, and occasionally double clicking a new widget also does nothing. While right clicking always gives you access to editing basic widget properties, it is annoying to constantly have to resort to this when a reasonable default action should be made available in the main design window.

Signals and Slots

At the heart of Qt is the signal/slot mechanism, which provides a clean abstraction of event handling. In Figure 5, Designer provides visual signal/slot editing that makes this mechanism intuitive while designing. Even if you have never programmed with Qt before, Designer exposes the most powerful parts of the Qt GUI library to you in an organized fashion.

In Qt, signals (which loosely correspond to events) are generated by objects at runtime. These signals are regular class methods that are marshaled by the Qt metaobject system and connected to other widgets via slots (which are also regular class methods). This is a flexible and powerful system for event handling, and it is used extensively throughout the Qt library. An extra precompilation step is necessary using the Meta Object Compiler (moc), which generates the metaobject code used internally by Qt when connecting signals to slots. There are advantages and disadvantages to implementing event handling in this way versus, for example, a template and function object-based approach (see, for example, http://libsigc.sourceforge.net/). However, the approach taken by Qt has proven itself over time to be flexible, portable, and fast enough, especially when it is considered that the cost of emitting signals as implemented by Qt is minor when compared to the cost of other code within GUI programs.

Creating new slots for your interface can be done in a number of different ways within Designer. While creating signal/slot connections, new slots can be defined for the window to handle them. Also, using the Signal Handler property editor, which displays all the signals generated by the selected widget, you can quickly define new slots that are automatically given reasonable names by Designer. In either case, empty virtual methods are automatically generated by Designer in the corresponding window's source code. While previous versions of Designer stopped at that point, the latest Designer lets you edit the source code for these new slots while you are designing.

For example, the bulk of the behavior in the Address Book example is handled by connecting various signals with slots implemented in the AddressBookImpl class, which is the topmost widget in the application. As a developer, you don't need to worry about all of the internal plumbing implemented by Qt to support signals and slots. Once you understand the concept behind signals/slots, this abstraction speeds up development.

The Integrated Editor

Designer's integrated source-code editor is pretty good. It provides syntax highlighting, automatic indentation, tab completion, and limited method name completion. Designer does its best to maintain synchronization between source code and GUI design by adding new methods in the Object Explorer when source code is edited, and automatically creating skeleton code when new methods are added via the IDE. There are a few situations where source code can fall out of sync with the visual design, most notably when you change the class name of a top-level widget. Because Designer cannot keep up with these types of changes, you get errors during compilation and must go back and figure out exactly where Designer lost track. It's best to design new windows, name controls, and finish the layout before getting into source-code editing.

Familiarity with Qt programming is helpful, but not necessary, when editing source code from within Designer. The Qt library is known for its intuitive class hierarchy and method names, so it's usually easy to accomplish what you want even without a good working knowledge of the library. For example, in the Address Book application, automatically updating line edit controls whenever a new list item is selected is easy to do in the AddressBook::newItemSelected() slot (Example 1).

The code you are editing for a window is actually a file included by the generated implementation of the widget. The window definition for the Address Book application is contained in addressbook.ui. At compile time, uic generates the corresponding .h and .cpp files that correspond to the design. The custom source code that was added to the AddressBook class is actually contained in addressbook.ui.h, which is included by the implementation of AddressBook in Figure 5. The name of the file containing the custom code for the AddressBook class is a bit of a misnomer, since this file is actually included directly in the implementation file, addressbook.cpp. It would have been more clear to name this file addressbook.ui.cpp. In any case, this included file relies on the class declaration generated by Designer; therefore, it is important to make sure that any methods added by hand into addressbook.ui.h are also recognized by Designer and added to the list of methods for the AddressBook class; otherwise, it will not compile. Normally, the source-code editor within Designer does a good job parsing the code and recognizing both new methods and changes to existing methods. Occasionally, though, the source code can get out of sync with Designer's definition, so it pays to keep an eye on the Object Explorer while editing source code to make sure it stays up to date. Hopefully, the next version of Designer will address some of these synchronization issues, since editing the source code for slots directly within Designer is by far the most useful feature of this tool.

The entire Address Book application, written completely within Designer instead of using inheritance (see Version 2), is available electronically.

Resource Management

Designer not only manages multiple window designs for a project, but also image and database resources. Consolidating all images from a project makes accessing image resources simple. Images are added to the project's Image Collection, and behind the scenes Designer generates all the code necessary to include the images into the compiled application, as well as registering the names of the images into the application's MIME factory so that they can be retrieved with a single function call:

addButton->setPixmap
( QPixmap::fromMimeSource( "logo.xpm" ) );

Internally, this static method searches the internal list of registered MIME types until it finds the "logo.xpm" resource that Designer generated. This could all be done by hand, of course, but Designer relieves you of the burden and generates reasonable code.

An important new feature in Qt 3.x is the SQL module. Designer has full support for not only adding database connection information to your projects, but also interactively allows you to design with data-aware controls, including data tables, browsers, and views. The Qt SQL module provides uniform access to a variety of databases by presenting a single API that is implemented by a variety of database-specific plug-ins for back ends such as Oracle, MySQL, PostgreSQL, and ODBC. The data-aware widgets in Qt (including QDataTable, QDataView, and QDataBrowser) give you access to efficient data displays as well as inline-editing of data directly from the database. Designer supports these widgets as fully as any other control, which makes development of nontrivial database applications with Designer just as easy as those created with database RAD tools, such as Microsoft Visual Basic. The main difference being, with Qt, the generated applications run natively on a wide variety of platforms with a simple recompile.

Custom Widgets and Templates

Adding your own widgets to Designer is usually necessary in any nontrivial program. Designer supports this by maintaining a list of custom widgets that can be added to windows like any other control, although it appears in the design window as an anonymous gray box (Version 3, available electronically, is another implementation of the Address Book application using a custom widget). Just adding your widget's class name and its relevant signals, slots, and properties to the Custom Widget dialog is enough to let you visually design with it. Designer generates the proper code to include your widget in the interface, and all you need to do is add your custom widget's implementation to the project.

Designer even supports custom widget plug-ins. This requires more coding on your part, but once completed, your custom widget will appear normally in the design window instead of as a gray box. This may be helpful for those who have separate developers working on GUI design as opposed to nonGUI application functionality, since they will be able to work with custom controls just as if it were any other control within Designer. In practice, it is usually sufficient to give Designer the top-level description of your custom widgets and skip the whole plug-in process.

Another helpful tool Designer supports are templates. These can be created for entire window designs, or can be created to provide base class functionality for entire groups of windows or other container widgets. As the name implies, templates provide preconfigured widget layouts that save you the trouble of recreating common layouts (Designer ships with some sample templates including Dialog and Main Window).

Conclusion

The environment in which C++ developers work has a big impact on productivity. Many are quite happy using emacs and a few terminals to develop their applications. Others prefer the bells and whistles of, for example, Microsoft Visual Studio. Between these two extremes lies Qt Designer.

Using Designer, C++ GUI application development with Qt is fast, maintainable, and flexible. You have access to all that the Qt library offers including sophisticated widgets, intuitive event handling, and database support. Designer manages entire C++ projects, and it can be customized and extended with user-defined widgets and templates. Designer can even be used on larger projects in such a way that the GUI design is a separate and distinct task from developing application functionality, which may be useful in some development shops.

The resulting code generated by Designer compiles and runs natively on almost any platform. Where Designer falls short is its lack of support for compilation. All other major IDEs support the compile/edit cycle extremely well, but Designer is remarkable in that it completely skirts this issue. If you are comfortable with compiling from the command line, you can appreciate this because Designer can essentially stay out of your way. However, it would be a major advantage to new developers if the option existed to launch a compile from within Designer, with the ability to track down compile errors and fix them from within the Designer IDE. Hardcore developers would still have the option to skip this step if they choose, but having the option to compile from within Designer would fill the last remaining hole in an otherwise useful and powerful GUI design tool.

DDJ


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.