The abstract base class for all items in a plot.
In QCustomPlot, items are supplemental graphical elements that are neither plottables (QCPAbstractPlottable) nor axes (QCPAxis). While plottables are always tied to two axes and thus plot coordinates, items can also be placed in absolute coordinates independent of any axes. Each specific item has at least one QCPItemPosition member which controls the positioning. Some items are defined by more than one coordinate and thus have two or more QCPItemPosition members (For example, QCPItemRect has topLeft and bottomRight).
This abstract base class defines a very basic interface like visibility and clipping. Since this class is abstract, it can't be instantiated. Use one of the subclasses or create a subclass yourself to create new items.
The built-in items are:
QCPItemLine | A line defined by a start and an end point. May have different ending styles on each side (e.g. arrows). |
QCPItemStraightLine | A straight line defined by a start and a direction point. Unlike QCPItemLine, the straight line is infinitely long and has no endings. |
QCPItemCurve | A curve defined by start, end and two intermediate control points. May have different ending styles on each side (e.g. arrows). |
QCPItemRect | A rectangle |
QCPItemEllipse | An ellipse |
QCPItemPixmap | An arbitrary pixmap |
QCPItemText | A text label |
QCPItemBracket | A bracket which may be used to reference/highlight certain parts in the plot. |
QCPItemTracer | An item that can be attached to a QCPGraph and sticks to its data points, given a key coordinate. |
Clipping
Items are by default clipped to the main axis rect (they are only visible inside the axis rect). To make an item visible outside that axis rect, disable clipping via setClipToAxisRect(false).
On the other hand if you want the item to be clipped to a different axis rect, specify it via setClipAxisRect. This clipAxisRect property of an item is only used for clipping behaviour, and in principle is independent of the coordinate axes the item might be tied to via its position members (QCPItemPosition::setAxes). However, it is common that the axis rect for clipping also contains the axes used for the item positions.
Using items
First you instantiate the item you want to use and add it to the plot:
by default, the positions of the item are bound to the x- and y-Axis of the plot. So we can just set the plot coordinates where the line should start/end:
If we don't want the line to be positioned in plot coordinates but a different coordinate system, e.g. absolute pixel positions on the QCustomPlot surface, we need to change the position type like this:
Then we can set the coordinates, this time in pixels:
and make the line visible on the entire QCustomPlot, by disabling clipping to the axis rect:
For more advanced plots, it is even possible to set different types and parent anchors per X/Y coordinate of an item position, using for example QCPItemPosition::setTypeX or QCPItemPosition::setParentAnchorX. For details, see the documentation of QCPItemPosition.
Creating own items
To create an own item, you implement a subclass of QCPAbstractItem. These are the pure virtual functions, you must implement:
See the documentation of those functions for what they need to do.
Allowing the item to be positioned
As mentioned, item positions are represented by QCPItemPosition members. Let's assume the new item shall have only one point as its position (as opposed to two like a rect or multiple like a polygon). You then add a public member of type QCPItemPosition like so:
the const makes sure the pointer itself can't be modified from the user of your new item (the QCPItemPosition instance it points to, can be modified, of course). The initialization of this pointer is made easy with the createPosition function. Just assign the return value of this function to each QCPItemPosition in the constructor of your item. createPosition takes a string which is the name of the position, typically this is identical to the variable name. For example, the constructor of QCPItemExample could look like this:
The draw function
To give your item a visual representation, reimplement the draw function and use the passed QCPPainter to draw the item. You can retrieve the item position in pixel coordinates from the position member(s) via QCPItemPosition::pixelPosition.
To optimize performance you should calculate a bounding rect first (don't forget to take the pen width into account), check whether it intersects the clipRect, and only draw the item at all if this is the case.
The selectTest function
Your implementation of the selectTest function may use the helpers QCPVector2D::distanceSquaredToLine and rectDistance. With these, the implementation of the selection test becomes significantly simpler for most items. See the documentation of selectTest for what the function parameters mean and what the function should return.
Providing anchors
Providing anchors (QCPItemAnchor) starts off like adding a position. First you create a public member, e.g.
and create it in the constructor with the createAnchor function, assigning it a name and an anchor id (an integer enumerating all anchors on the item, you may create an own enum for this). Since anchors can be placed anywhere, relative to the item's position(s), your item needs to provide the position of every anchor with the reimplementation of the anchorPixelPosition(int anchorId) function.
In essence the QCPItemAnchor is merely an intermediary that itself asks your item for the pixel position when anything attached to the anchor needs to know the coordinates.
virtual double QCPAbstractItem::selectTest |
( |
const QPointF & |
pos, |
|
|
bool |
onlySelectable, |
|
|
QVariant * |
details = 0 |
|
) |
| const |
|
pure virtual |
This function is used to decide whether a click hits a layerable object or not.
pos is a point in pixel coordinates on the QCustomPlot surface. This function returns the shortest pixel distance of this point to the object. If the object is either invisible or the distance couldn't be determined, -1.0 is returned. Further, if onlySelectable is true and the object is not selectable, -1.0 is returned, too.
If the object is represented not by single lines but by an area like a QCPItemText or the bars of a QCPBars plottable, a click inside the area should also be considered a hit. In these cases this function thus returns a constant value greater zero but still below the parent plot's selection tolerance. (typically the selectionTolerance multiplied by 0.99).
Providing a constant value for area objects allows selecting line objects even when they are obscured by such area objects, by clicking close to the lines (i.e. closer than 0.99*selectionTolerance).
The actual setting of the selection state is not done by this function. This is handled by the parent QCustomPlot when the mouseReleaseEvent occurs, and the finally selected object is notified via the selectEvent/ deselectEvent methods.
details is an optional output parameter. Every layerable subclass may place any information in details. This information will be passed to selectEvent when the parent QCustomPlot decides on the basis of this selectTest call, that the object was successfully selected. The subsequent call to selectEvent will carry the details. This is useful for multi-part objects (like QCPAxis). This way, a possibly complex calculation to decide which part was clicked is only done once in selectTest. The result (i.e. the actually clicked part) can then be placed in details. So in the subsequent selectEvent, the decision which part was selected doesn't have to be done a second time for a single selection operation.
You may pass 0 as details to indicate that you are not interested in those selection details.
- See also
- selectEvent, deselectEvent, mousePressEvent, wheelEvent, QCustomPlot::setInteractions
Reimplemented from QCPLayerable.
Implemented in QCPItemBracket, QCPItemTracer, QCPItemPixmap, QCPItemEllipse, QCPItemText, QCPItemRect, QCPItemCurve, QCPItemLine, and QCPItemStraightLine.