11. QWT

QWT is short for Qt Widgets for Technical Applications. It is a collection of widgets and support classes for creating technical applications such as those created using, for example, LabView or Test Point.

This chapter covers the installation of the library and a brief coverage of many of the supplied widgets. For the interested reader details can be found at in the official documentation.

Qwt, version 0.4.1 is used through-out this chapter.

Installation

First of all, this only covers the installation of the library on a Unix platform (I use Mandrake Linux). The home site has information concerning the installation on other platforms. The installation uses qmake/tmake and should thus be highly portable.

First, go the the QWT homepage using your favourite browser, or simply download the source directly from the SourceForge project page. Untar it. From now on, the directory containing QWT will be refered to as $(QWT). To setup the environment for that, cd into the QWT directory and type export QWT=`pwd`.

What the installation instruction (available on-line) tells you is to run qmake qwt.pro -o Makefile and then to run make. This will build the library. Now, as a Unix user, put symlinks to a place in LD_LIBRARY_PATH (such as /usr/lib) to the files of the $(QWT)/lib directory, or modify LD_LIBRARY_PATH to include that directory.

This means that the library is installed, and now, all you have to do to use it is to include the $(QWT)/include directory in the INCLUDEPATH of your project files and use the -lqwt switch when linking.

Basic Plotting

In this section the details of showing a trivial plot will be covered. The example consists of a custom widget inherited from the QwtPlot class. The QwtPlot class embedds most of the plotting capabilites of the Qwt library. The code of the derived class, MyPlot is shown in example 11-1.

class MyPlot : public QwtPlot
{
public:
  MyPlot( QWidget *parent=0, char *name=0 ) : QwtPlot( parent, name )
  {
    // Show a title
    setTitle( "This is an Example" );

    // Show a legend at the bottom
    setAutoLegend( true );
    setLegendPos( Qwt::Bottom );

    // Show the axes
    setAxisTitle( xBottom, "x" );
    setAxisTitle( yLeft, "y" );

    // Insert two curves and get IDs for them
    long cSin = insertCurve( "y = sin(x)" );
    long cSign = insertCurve( "y = sign(sin(x))" );

    // Calculate the data, 500 points each
    const int points = 500;
    double x[ points ];
    double sn[ points ];
    double sg[ points ];

    for( int i=0; i<points; i++ )
    {
      x[i] = (3.0*3.14/double(points))*double(i);
    
      sn[i] = 2.0*sin( x[i] );
      sg[i] = (sn[i]>0)?1:((sn[i]<0)?-1:0);
    }

    // Copy the data to the plot
    setCurveData( cSin, x, sn, points );
    setCurveData( cSign, x, sg, points );

    // Set the style of the curves
    setCurvePen( cSin, QPen( blue ) );
    setCurvePen( cSign, QPen( green, 3 ) );

    // Show the plots
    replot();
  }
};

Example 11-1

The derived class simply initializes the plot in the constructor. The code comments show where each action takes place, but the details are explained in the next paragraphs.

The first thing that happens is that the title is set and an automatically generated legend is turned on. The legend will be placed at the bottom of the widget, i.e. below the plot. All curves that are added to the plot when the auto legend is turned on will be added to the plot.

Now, the axes are given titles. As can be seen from the documentation of setAxisTitle (yes, Qwt has on-line reference documentation with example code) the titles are placed to the left and at the bottom. Finally two curve IDs are retrieved before dummy data is generated. The data is irrelevant to the example but ends up in two curves. The data for these curves are then copied to the plot by the calls to setCurveData.

The last task performed before a forced replot is that the pen styles to be used for each curve is set.

In order to show the plot, an instance of the widget has to be created. That is done in the trivial main shown in example 11-2.

int main( int argc, char **argv )
{
  QApplication a( argc, argv );

  MyPlot p;
  a.setMainWidget( &p );
  p.show();

  return a.exec();
}

Example 11-2

Advanced Plotting

The QwtPlot widget is good for most plotting needs. It is however based on a whole range of Qwt classes that provide more direct control over the plotting. This section will introduce some of these classes, but the interested reader is recommended to look at the official documentation for further details.

The QwtCurve class is used to handle curve instances. This class offers control over apperance, interpolation methods and such. For efficient data representation, for example, live, request-based filtering, can be implemented as a QwtData sub-class. These two classes combined provides total control of the data shown.

Instead of offering a widget, QwtCurve has a draw method. By calling this from a custom widget, any plotting widget can be created. This also makes it possible to use the class for printing. The QwtDiMaps used in the call are used to map a real value interval onto an integer interval. It can handle both linear and logarithmic mappings.

To complete any plot drawing widget, a grid of some sort is needed. This is handled through the QwtGrid class. This class also works as the QwtCurve class and offers a draw method to be used in a painting routine.

Widgets

Qwt offers many widgets. In this section three of them, a knob, a slider and a wheel will be demonstrated. Figure 11-1 shows what the example application will look like.

Qwt Widgets

Figure 11-1 Qwt Widgets

These widgets provide signals and slots that can be expected from any Qt widget and can thus easily be inter-connected to show the same value at all times. Example 11-3 shows the example class that holds the widgets. Notice that it is derived from a QHBox so that it automatically arranges its child widgets.

class MyWidgetWidget : public QHBox
{
public:
  MyWidgetWidget( QWidget *parent=0, char *name=0 ) : QHBox( parent, name )
  {
    // A knob
    QwtKnob *knob = new QwtKnob( this );
    
    // A slider
    QwtSlider *slider = new QwtSlider( this, "", Qt::Vertical, QwtSlider::Left );
    
    // A wheel
    QwtWheel *wheel = new QwtWheel( this );
    wheel->setOrientation( Qt::Vertical );
    wheel->setTotalAngle( 360*5 );

    // Setup the ranges
    knob->setRange( 0.0, 1000.0 );
    slider->setRange( 0.0, 1000.0 );
    wheel->setRange( 0.0, 1000.0 );

    // Connect the widgets to each other
    connect( knob, SIGNAL(valueChanged(double)), slider, SLOT(setValue(double)) );
    connect( knob, SIGNAL(valueChanged(double)), wheel, SLOT(setValue(double)) );

    connect( slider, SIGNAL(valueChanged(double)), knob, SLOT(setValue(double)) );
    connect( slider, SIGNAL(valueChanged(double)), wheel, SLOT(setValue(double)) );

    connect( wheel, SIGNAL(valueChanged(double)), knob, SLOT(setValue(double)) );
    connect( wheel, SIGNAL(valueChanged(double)), slider, SLOT(setValue(double)) );
  }
};

Example 11-3

This code should not have any surprises. Notice that the default orientation of the wheel and slider is horizontal and that the slider does not show any scale unless a position is specified. This can be done either using the constructor as in the example code here or the setScalePos method.

To show the widget the trivial main from example 11-4 is used.

int main( int argc, char **argv )
{
  QApplication a( argc, argv );

  MyWidgetWidget w;
  a.setMainWidget( &w );
  w.show();

  return a.exec();
}

Example 11-4

qmake is used to build the example. Example 11-5 shows the result from running qmake -project in the example directory (the directory is called wid and the example source is in the wid.cpp file).

######################################################################
# Automatically generated by qmake (1.04a) Sun Feb 22 16:54:26 2004
######################################################################

TEMPLATE = app
CONFIG -= moc
INCLUDEPATH += .

# Input
SOURCES += wid.cpp

Example 11-5

Example 11-6 shows the modified project file that makes it possible to use Qwt. Notice that this requires the QWT environment variable to be setup as described earlier in this chapter.

######################################################################
# Automatically generated by qmake (1.04a) Thu Feb 19 20:44:51 2004
######################################################################


TEMPLATE = app
CONFIG -= moc
INCLUDEPATH += $(QWT)/include
LIBS += -lqwt

# Input
SOURCES += wid.cpp

Example 11-6

To build the example, simply type qmake && make && ./wid at the console.

Summary

There is no example source available for this chapter.

Exercises

This is a part of digitalfanatics.org and is valid XHTML.