Difference between revisions of "Development/Tutorials/KPlotWidget"

Jump to: navigation, search
(addObject -> addPlotObject)
m (Text replace - "<code cppqt>" to "<syntaxhighlight lang="cpp-qt">")
Line 22: Line 22:
 
Basic usage of KPlotWidget is illustrated with the following example:
 
Basic usage of KPlotWidget is illustrated with the following example:
  
<code cppqt>
+
<syntaxhighlight lang="cpp-qt">
 
// Create a new KPlotWidget, provide a minimum size,  
 
// Create a new KPlotWidget, provide a minimum size,  
 
// and activate antialiased drawing:
 
// and activate antialiased drawing:
Line 56: Line 56:
 
The data points in a {{class|KPlotObject}} can be rendered in a number of ways: as discrete points, connected line segments, or bar-graph style rectangles.  In fact, the same KPlotObject can be rendered in any combination of these styles; here is an example of a KPlotObject which will be rendered with all three styles:
 
The data points in a {{class|KPlotObject}} can be rendered in a number of ways: as discrete points, connected line segments, or bar-graph style rectangles.  In fact, the same KPlotObject can be rendered in any combination of these styles; here is an example of a KPlotObject which will be rendered with all three styles:
  
<code cppqt>
+
<syntaxhighlight lang="cpp-qt">
 
po = new KPlotObject( Qt::white, KPlotObject::Points, 10, KPlotObject::Pentagon );
 
po = new KPlotObject( Qt::white, KPlotObject::Points, 10, KPlotObject::Pentagon );
 
po->setShowLines( true );
 
po->setShowLines( true );
Line 75: Line 75:
 
By default, the same {{qt|QPen}} and {{qt|QBrush}} will be used to render the Points, Lines, and Bars.  The color of the default pen and brush are set in the constructor.  However, it is easy to provide custom pens and brushes for the different plot styles:
 
By default, the same {{qt|QPen}} and {{qt|QBrush}} will be used to render the Points, Lines, and Bars.  The color of the default pen and brush are set in the constructor.  However, it is easy to provide custom pens and brushes for the different plot styles:
  
<code cppqt>
+
<syntaxhighlight lang="cpp-qt">
 
// Modify the pen used to draw Lines connecting  
 
// Modify the pen used to draw Lines connecting  
 
// data points in this KPlotObject:
 
// data points in this KPlotObject:
Line 92: Line 92:
 
done like this:
 
done like this:
  
<code cppqt>
+
<syntaxhighlight lang="cpp-qt">
 
// "plot" is a KPlotWidget containing several KPlotObject data sets,
 
// "plot" is a KPlotWidget containing several KPlotObject data sets,
 
// each of which consists of several  KPlotPoints
 
// each of which consists of several  KPlotPoints
Line 125: Line 125:
 
Besides setting the colors of KPlotObjects (using KPlotObject::setPen(), setLinePen(), setBrush(), etc), you can also customize three color elements for the plot as a whole: the background, foreground and grid colors.  The functions for this are:
 
Besides setting the colors of KPlotObjects (using KPlotObject::setPen(), setLinePen(), setBrush(), etc), you can also customize three color elements for the plot as a whole: the background, foreground and grid colors.  The functions for this are:
  
<code cppqt>
+
<syntaxhighlight lang="cpp-qt">
 
KPlotWidget::setBackgroundColor( const QColor& );
 
KPlotWidget::setBackgroundColor( const QColor& );
 
KPlotWidget::setForegroundColor( const QColor& );
 
KPlotWidget::setForegroundColor( const QColor& );
Line 138: Line 138:
  
 
If you would like your plot to include a grid overlay, simply add:
 
If you would like your plot to include a grid overlay, simply add:
<code cppqt>plot->setShowGrid(true)</code>
+
<syntaxhighlight lang="cpp-qt">plot->setShowGrid(true)</code>
 
The grid lines are placed at the positions of major tickmarks along the Bottom and Left axes.
 
The grid lines are placed at the positions of major tickmarks along the Bottom and Left axes.
  
Line 157: Line 157:
 
The secondary data limits are stored internally as a QRectF, just like the primary limits.  To set the secondary limits, so something like:
 
The secondary data limits are stored internally as a QRectF, just like the primary limits.  To set the secondary limits, so something like:
  
<code cppqt>
+
<syntaxhighlight lang="cpp-qt">
 
plot->setSecondaryLimits( -5.73, 365.55, -1.1, 1.1 );
 
plot->setSecondaryLimits( -5.73, 365.55, -1.1, 1.1 );
 
plot->axis(KPlotWidget::TopAxis)->setTickLabelsShown( true );
 
plot->axis(KPlotWidget::TopAxis)->setTickLabelsShown( true );

Revision as of 21:29, 29 June 2011

Introduction and Scope

KPlotWidget is used for easily creating 2-D plots of data sets, complete with plot axes that include labeled tickmarks and optional axis labels. Data sets can be represented as any combination of: discrete points (using a variety of point shapes), connected line segments (using any QPen), or bar-graph rectangles (using any QPen/QBrush). In addition, any data point can have a label string attached to it.

Here is a simple example showing sine and cosine curves:

Kplot.jpg

This example demonstrates most of the commonly-used features of KPlotWidget. It is included in KDE, under kdelibs/kdeui/tests. The first part of this tutorial will explain how to produce this plot using KPlotWidget.

Basic Usage

The data to be plotted in KPlotWidget are stored as a list of KPlotObjects. Each KPlotObject itself consists of a list of KPlotPoints (which store the coordinates of each data point, as well as an optional text label), and methods to modify the parameters which control how they are drawn in the plot. KPlotWidget also contains four KPlotAxis objects, which encapsulate the plot axes, tickmarks, tickmark labels, and axis labels along the four edges bounding the plot.

KPlotWidget takes care of much of the plot rendering automatically, so simple data plots can be done with just a few lines of code:

  • The area shown in the plot is determined from the range of the data in the KPlotObjects
  • Tickmark positions are optimally computed, and synced between the top/bottom and left/right axes
  • Tickmark labels are placed automatically along the left and bottom axes
  • The padding area outside the axes is adjusted according to whether tickmark labels and/or axis labels are being drawn
  • Data points are automatically transformed from their natural units to screen-pixel coordinates. In most cases, you will not have to care about pixel coordinates at all.

Basic usage of KPlotWidget is illustrated with the following example:

// Create a new KPlotWidget, provide a minimum size, 
// and activate antialiased drawing:
KPlotWidget *plot = new KPlotWidget( parent );
plot->setMinimumSize( 400, 400 );
plot->setAntialiasing( true );
 
// Set the boundaries of the plot to display the full extent of the sine curve:
plot->setLimits( -0.1, 6.38, -1.1, 1.1 );
 
// Create a KPlotObject which will display data 
// points by connecting them with red line segments
// with a width of 2 pixels:
KPlotObject *sineobj = new KPlotObject( Qt::red, KPlotObject::Lines, 2 );
 
// Add data points to the KPlotObject for a 
// sine curve (these are stored internally 
// as KPlotPoints):
for ( float t=0.0; t<=6.28; t+=0.04 ) 
    sineobj->addPoint( t, sin(t) );
 
// Add the KPlotObject to the plot:
plot->addPlotObject( sineobj );
 
// Add a text label to the bottom axis:
plot->axis( KPlotWidget::BottomAxis )->setLabel( i18n("Angle in radians") );
 
plot->update();
</code>
 
=== Rendering Options for KPlotObjects ===
 
The data points in a {{class|KPlotObject}} can be rendered in a number of ways: as discrete points, connected line segments, or bar-graph style rectangles.  In fact, the same KPlotObject can be rendered in any combination of these styles; here is an example of a KPlotObject which will be rendered with all three styles:
 
<syntaxhighlight lang="cpp-qt">
po = new KPlotObject( Qt::white, KPlotObject::Points, 10, KPlotObject::Pentagon );
po->setShowLines( true );
po->setShowBars( true );
</code>
 
Note that when constructing a KPlotObject which will be rendered as Points, 
the third argument is the size of the points in pixels, and the fourth argument describes the shape to use when rendering each point.  The options are:
 
* Circle
* Triangle
* Square
* Pentagon
* Hexagon
* Asterisk
* Star
 
By default, the same {{qt|QPen}} and {{qt|QBrush}} will be used to render the Points, Lines, and Bars.  The color of the default pen and brush are set in the constructor.  However, it is easy to provide custom pens and brushes for the different plot styles:
 
<syntaxhighlight lang="cpp-qt">
// Modify the pen used to draw Lines connecting 
// data points in this KPlotObject:
po->setLinePen( QPen( Qt::red, 3.0, Qt::DashDotLine ) );
 
// Modify the brush used to fill Bars in this 
// KPlotObject:
po->setBarBrush( QBrush( Qt::blue, Qt::BDiagPattern ) );
</code>
 
=== Traversing All Data Points ===
 
Both KPlotWidget and KPlotObject provide functions that return 
the list of KPlotObjects and KPlotPoints that they contain, so if 
one needed to access all of the data points in the plot, it can be 
done like this:
 
<syntaxhighlight lang="cpp-qt">
// "plot" is a KPlotWidget containing several KPlotObject data sets,
// each of which consists of several  KPlotPoints
foreach( KPlotObject *po, plot->plotObjects() ) {
    foreach( KPlotPoint *p, po->points() ) {
        // Do stuff to each KPlotPoint
    }
}
</code>
 
=== Labeling Data Points ===
 
Text labels can be attached to any point in a KPlotObject.  
The easiest way to accomplish this is to add the label text as 
the second argument to 
KPlotObject::addPoint( const QPointF&, const QString& ).  There 
is also a KPlotPoint::setLabel( const QString& ) function, if you 
need to add a text label after the point has already been created.
 
Note that KPlotWidget will automatically try to place the labels 
intelligently, so that each label is close to its point without 
overlapping other labels or plot elements.  If a label needs to 
be placed at some distance from its point, then the label and 
point will be connected with a line segment.
 
== Customizing the plot ==
 
The basic usage outlined above will usually suffice for simple data plots.  However, the time may come when you need more flexibility.  Many aspects of the plot rendering which are normally done automatically can be manually overidden.
 
=== Custom Colors for the Plot Area ===
 
Besides setting the colors of KPlotObjects (using KPlotObject::setPen(), setLinePen(), setBrush(), etc), you can also customize three color elements for the plot as a whole: the background, foreground and grid colors.  The functions for this are:
 
<syntaxhighlight lang="cpp-qt">
KPlotWidget::setBackgroundColor( const QColor& );
KPlotWidget::setForegroundColor( const QColor& );
KPlotWidget::setGridColor( const QColor& );
</code>
 
The background color is self-explanatory; its default is black.<br>
The foreground color is used for drawing the axes and their labels; its default is white.<br>
The grid color is used for drawing the optional grid on the plot (see the next section in this tutorial); its default is grey.<br>
 
=== Showing a grid ===
 
If you would like your plot to include a grid overlay, simply add:
<syntaxhighlight lang="cpp-qt">plot->setShowGrid(true)</code>
The grid lines are placed at the positions of major tickmarks along the Bottom and Left axes.
 
=== The Padding Area ===
 
By default, KPlotWidget will automatically compute how much padding is needed outside of each Axis, to provide room for tickmark labels and/or the axis label, if they are present.  If you need to override these calculations, the padding on each axis can be set manually with the functions setTopPadding(int), setBottomPadding(int), setLeftPadding(int), or setRightPadding(int), where the argument is the size of the padding in pixels.
 
If you need to restore the automatic calculation of the axis padding, you can set the padding of any axis to -1, or use setDefaultPaddings() to restore all four axes at once.
 
=== Providing Secondary Data Limits ===
 
By default, the top and right axes show the same tickmarks as the bottom and left axes.  However, it is possible to define secondary data limits for your data set which will be displayed on the top and right axes.
 
Why would one want to do this?  One possibility is shown in the example image at the beginning of this tutorial: you may want to express the data using two different units.  In the case of the example, we are plotting angles on the x-axis; the angles are shown in both degrees (top axis) and in radians (bottom axis).
 
In any case, bear in mind that the secondary data limits are not used for anything other than rendering the top and right axes; all internal calculations use the primary data limits only.  Also, no check is made to make sure that the secondary limits are actually mapped correctly to the primary limits.
 
The secondary data limits are stored internally as a QRectF, just like the primary limits.  To set the secondary limits, so something like:
 
<syntaxhighlight lang="cpp-qt">
plot->setSecondaryLimits( -5.73, 365.55, -1.1, 1.1 );
plot->axis(KPlotWidget::TopAxis)->setTickLabelsShown( true );
plot->axis(KPlotWidget::TopAxis)->setLabel("Angle [degrees]")
</code>
 
The first command tells the top axis to cover values -5.73 to 365.55, and the right axis to cover values -1.1 to 1.1.  The second command tells the plot to draw tick labels along the top axis, and the third command adds an axis label to the top axis.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V.Legal