QCustomPlot Discussion and Comments

Rescale plot to show all plottables AND all itemsReturn to overview

Hi

Seems like QCPAbstractPlottable::rescaleAxes() only makes sure that all plottables are visible, while it does not make sure all items are visible as well.

My use case is: The user selects a plot and I add an item containing more information about selected point. The problem is that I need to rescale the plot in order for the added item not too be cut off by the edges of the plot. The user has the option to switch the axis from linear to logarithmic, so it becomes tricky to know how much to manually scale the axis with.

Is there a way to do this automatically?

There is always the possibility that its because of the way I add the item. To rule that out, this is how I add the item:

QCPItemText *improvement_text = new QCPItemText(this);
addItem("some text:);
improvement_text->position->setParentAnchor(some point on the selected item);

Thanks

JPN,

I beleive items are not part of the rescale functions since they can be positioned in various ways.

  enum PositionType { ptAbsolute        ///< Static positioning in pixels, starting from the top left corner of the viewport/widget.
                      ,ptViewportRatio  ///< Static positioning given by a fraction of the viewport size. For example, if you call setCoords(0, 0), the position will be at the top
                                        ///< left corner of the viewport/widget. setCoords(1, 1) will be at the bottom right corner, setCoords(0.5, 0) will be horizontally centered and
                                        ///< vertically at the top of the viewport/widget, etc.
                      ,ptAxisRectRatio  ///< Static positioning given by a fraction of the axis rect size (see \ref setAxisRect). For example, if you call setCoords(0, 0), the position will be at the top
                                        ///< left corner of the axis rect. setCoords(1, 1) will be at the bottom right corner, setCoords(0.5, 0) will be horizontally centered and
                                        ///< vertically at the top of the axis rect, etc. You can also go beyond the axis rect by providing negative coordinates or coordinates larger than 1.
                      ,ptPlotCoords     ///< Dynamic positioning at a plot coordinate defined by two axes (see \ref setAxes).
                    };

If you position them by using the QCPItemPosition::ptPlotCoords you can try and adjust the viewport of the widget with QCPAxis::setRange() (overscale the visible region by adding the items sizes in consideration).

Ross

Hi Ross

Thanks for the reply. I'm currently using setRange() manually, but I have continued issues with the ranges to use. For example:

If I have data max = 10, then I set the upper range of the y-axis to max + (max * 0.05) and everything fits nicely. However, if the max is 100 000 then the extra space is not enough. Another problem is that the user has the ability to switch between linear and logarithmic y-axis. So I do the manually range adjustment for both cases. For the logarithmic case I use a different adjustment: max + (max * 0.1).

I find that with big numbers the adjustment is not enough, and with small numbers it is too much.

Is there a better way to do/calculate this?

Thanks

JPN,

It's a good idea to add a certain coefficient when setting the range, furthermore, you can enhance that logic by using an elided version of the text (try QFontMetrics), add margins and padding in the mix, crunch those numbers to set the viewport accordingly.

Ross

Hi,

I also used coefficients to adjust the plot range so that text items are shown. However, it didn't work so well for large range changes, nor did it work well when using logarithmic scale. I decided to try and find a better way to achieve the same thing without altering plot range.

My idea is to allow QCPItemText to be rendered outside the plot axis rectangle, ensuring it will be shown when it cannot fit inside the plot:

textItem->setClipToAxisRect(false);

In order for this to work, you need to "reserve" some space for the text item between the plot's axis rectangle and the plot's widget bounds by using margins:

customtPlot->axisRect()->setMargins(QMargins( 0, 0, 50, 0 ));
Here I reserved 50 pixels for my text item to be shown right of the axis rectangle.

The down side is that you are sacrificing some screen real estate of your plotting rectangle.

I hope this solution proves useful to someone.

Regards, Namik

Very helpful. Thanks.