PDA

View Full Version : Best way to calculate fixed width for QwtScaleWidget?



SeanM
5th June 2014, 19:37
I'm trying to figure out what the best way is to calculate a fixed width needed for a QwtScaleWidget.

Here's my issue:
I've got an application with multiple QwtPlots aligned vertically on pages of a QTabWidget. The plots all share a common x-axis and are meant to stay vertically aligned, but the y-axis values can vary greatly between individual plots. As the y-axis min/max change on individual plots due to data values changing, the width of the QwtScaleWidget changes to accommodate, causing the plots to shift around a little which just looks funny to the user. For example, if the y-axis max changes from 10 to 1000, the scale needs to grow a little bit wider to accommodate the additional zeroes, and since the parent widget isn't resizing, the plot shrinks a little bit in width. I then need to resize all the other plots to the same width to keep them lined up. This looks somewhat visually jarring.

I do know up front what the absolute data limits could be (our highest value can't be greater than 5 digits long). So rather than have the scale widget auto resize based on current text string lengths, I'd prefer to just set them to the width needed for our data maximum, even if that means often times they'll be wider than strictly necessary. To be clear, I still want the values of the scale to auto-scale, I just don't want the current values of the scale to affect the width of the widget.

So I know could use QFontMetrics and my largest allowed value to figure out how many pixels I need to accommodate the longest string based on the current font, but what other parameters do I need to know, and how do I get access to them? Looking at the widget in action, it appears that I also need to take into account the width of the tick marks, probably some sort of spacing in between the text and the tick marks, and then maybe some margin around everything?

I can't quite tell from the documentation if
int QwtScaleWidget::dimForLength (int length, const QFont &scaleFont) const is intended to do what I want? If it is, I'm not sure what I'm supposed to put in for the length parameter?

Uwe
6th June 2014, 07:03
Check the plotmatrix example.

Uwe

SeanM
6th June 2014, 15:47
Check the plotmatrix example

Are you referring to the function PlotMatrix::alignVAxes(), where you're looping through the rows and setting the minimum extent of the scale draw widgets? If so, that's not exactly the case I'm describing. Or maybe I'm just misunderstanding your hint? In your example, you're setting the minimum extent of all scale widgets to what it needs to be for the widest scale widget based on the current values set on each plot's scale widget. So there's two issues with that for what I need. First, since you're only setting minimum extent, there's nothing that prevents the widget from grow wider as the scale changes to require extra digit(s). I'm guessing the fix for that is call setFixedWidth(maxExtent) instead of setMinimumExtent(maxExtent). But that leads to the second problem, which I think is my real issue, you're only calculating maxExtent based on the current values, not the potential value that could happen later.

For example, say I have a simple setup where I only have two vertically aligned plots. The first plot is starts scaled from 0 to 1. The second plot is starts scaled from 0 to 10. However, I know that the user could choose to add a data curve that needs to be scaled from 0 to 10000. What I need to do is set a fixed width based on a value that isn't necessarily set on any of the scale widgets yet. So from the time my application launches, I want to set the width of all the scale widgets to be large enough to hold 10000 without the scale widget ever needing a resize, the only time I'd ever need to resize the scale widgets is if the user changed the application font.

So in my above example, calling QwtScaleDraw::extent(QFont) on either of the two existing plots won't give me the correct answer, since it would only return the size needed to show a "1" or a "10", not the size needed to show a "10000".

Or are you suggesting that when my application launches, I should immediately create a plot, set the scale to 10000, call extent() at that point, call setFixedWidth() with that value, and then return the plot to the default scale? I'm a little worried that might cause a flicker, but I could try it.

Uwe
6th June 2014, 17:30
If the width is calculated from another scale or some maximum related to f.e QFontMetrics::width( "100000.000" ) - in the end it is always about setting QwtScaleDraw::setMinimumExtent().

Uwe

SeanM
6th June 2014, 18:02
Ok, I get that you're saying the right function to call is QwtScaleDraw::setMinimumExtent(double minExtent).

I'm still unsure how to calculate the correct value for minExtent to pass to that function? My understanding is the value I want to pass in for minExtent is the width (in pixels) of my text string, plus the width of the tick marks, plus some more pixels for spacing/margins. So font metrics alone isn't enough to give me the extent I need. So I'm just unsure of how to take into account all the scale widget component widths to arrive at the appropriate value.