Chapter 5. Creating Custom Widgets

Table of Contents
Simple Custom Widgets
Creating Custom Widgets with Plugins

Custom widgets are created in code. They may comprise a combination of existing widgets but with additional functionality, slots and signals, or they may be written from scratch, or a mixture of both.

Qt Designer provides two mechanisms for incorporating custom widgets:

  1. The original method involves little more than completing a dialog box. Widgets incorporated this way appear as flat pixmaps when added to a form in Qt Designer, even in preview mode. They only appear in their true form at runtime. We'll explain how to create custom widgets using the original approach in "Simple Custom Widgets".

  2. The new method involves embedding the widgets in a plugin. Widgets that are incorporated through plugins appear in their true form in Qt Designer, both when laying out the form and in preview mode. This approach provides more power and flexibility than the original method and is covered in the section called Creating Custom Widgets with Plugins "Creating Custom Widgets with Plugins"

Simple Custom Widgets

There are two stages to creating a custom widget. Firstly we must create a class that defines the widget, and secondly we must incorporate the widget into Qt Designer. Creating the widget has to be done whether we are creating a simple custom widget or a plugin, but for simple custom widgets the incorporation into Qt Designer is very easy.

We will create a VCR style widget comprising four buttons, rewind, play, next and stop. The widget will emit signals according to which button is clicked.

Coding the Custom Widget

A custom widget may consist of one or more standard widgets placed together in a particular combination, or may be written from scratch. We will combine some QPushButton widgets to form the basis of our custom widget.

We'll look at the header file, qt/tools/designer/examples/vcr/vcr.h first.
#ifndef VCR_H
#define VCR_H
#include <qwidget.h>

class Vcr : public QWidget
{
    Q_OBJECT
public:
    Vcr( QWidget *parent = 0, const char *name = 0 );
    ~Vcr() {}
signals:
    void rewind();
    void play();
    void next();
    void stop();
};
#endif
We include qwidget.h since we'll be deriving our custom widget from QWidget. We declare a constructor where the widget will be created and the four signals we want our widget to emit. Since we're using signals we must also include the Q_OBJECT macro.

The implementation is straightforward. The only function we implement is the constructor. The rest of the file consists of include statements and embedded .xpm images.
Vcr::Vcr( QWidget *parent, const char *name )
    : QWidget( parent, name )
{
    QHBoxLayout *layout = new QHBoxLayout( this );
    layout->setMargin( 0 );

    QPushButton *rewind = new QPushButton( QPixmap( rewind_xpm ), 0, this, "vcr_rewind" );
    layout->addWidget( rewind );
    connect( rewind, SIGNAL(clicked()), SIGNAL(rewind()) ); 
We create a QHBoxLayout in which we'll place the buttons. We've only shown the rewind button in the code above since all the others are identical except for the names of the buttons, pixmaps and signals. For each of the buttons we require we call the QPushButton constructor passing it the appropriate embedded pixmap. We then add it to the layout. Finally we connect the button's clicked() signal to the appropriate signal. Since the clicked() signals aren't specific to our widget we want to emit signals that reflect the widget's use. The rewind(), play(), etc. signals are meaningful in the context of our widget so we propagate each button's clicked() signal to the appropriate widget-specific signal.

The implementation is complete, but to make sure that our widget compiles and runs we'll create a tiny test harness. The test harness will require two files, a .pro project file and a main.cpp. The qt/tools/designer/examples/vcr/vcr.pro project file:
TEMPLATE = app
CONFIG+= qt warn_on release
HEADERS  = vcr.h
SOURCES  = vcr.cpp main.cpp
TARGET   = vcr
The qt/tools/designer/examples/vcr/main.cpp file is also brief:
#include <qapplication.h>
#include "vcr.h"

int main( int argc, char ** argv )
{
    QApplication app( argc, argv );
    Vcr *vcr = new Vcr;
    vcr->show();
    return app.exec();
}
Once we're satisfied that the custom widget compiles and runs we are ready to incorporate it into Qt Designer.

In the section called Base-class Templates in Chapter 7 "Base-class Templates" the creation of a container custom widget is described.

Adding the Custom Widget to Qt Designer

Click Tools|Custom|Edit Custom Widgets to invoke the Edit Custom Widgets dialog.

  1. Click New Widget so that we are ready to add our new widget.

  2. Change the Class name from 'MyCustomWidget' to 'Vcr'.

  3. Click the ellipsis (...) button to the right of the Headerfile line edit to invoke the file Open dialog. Locate vcr.h, select it, and click Open. It will now appear as the header file.

  4. If you have a pixmap that you want to use to identify your widget on the toolbar click the ellipsis button to the right of Pixmap.

    In our example we have the file qt/tools/designer/examples/vcr/play.xpm which we'll use for this purpose.

  5. Since we know the minimum sensible size for our widget we'll put these values into the Size Hint spin boxes. Enter a width of 80 (in the left hand spin box), and a height of 20 (in the right hand spin box).

The remaining items to be completed will depend on the characteristics of the widget you've created. If, for example, your widget can be used to contain other widgets you'd check the Container Widget checkbox. In the case of our Vcr example the only items we need to add are its signals.

Click the Signals tab. Click the New Signal button and type in the signal name 'rewind()'. Click New Signal again and this time type in 'play()'. Add the 'next()' and 'stop()' signals in the same way.

Since our example hasn't any slots or properties we've finished and can click Close. A new icon will appear in Qt Designer's toolbars which represents the new widget. If you create a new form you can add Vcr widgets and connect the Vcr's signals to your slots.

Incorporating custom widgets that have their own slots and properties is achieved in a similar way to adding signals. All the required information is in our custom widget's header file.