src/RangedSlider.cpp

changeset 100
d11a3e713e3b
parent 99
053c0578cf58
child 101
1d14d3bf2465
equal deleted inserted replaced
99:053c0578cf58 100:d11a3e713e3b
51 _prefRangePen(Qt::NoPen), 51 _prefRangePen(Qt::NoPen),
52 _markerBrush(QColor(255,255,255)), 52 _markerBrush(QColor(255,255,255)),
53 _markerTextIsValue(false), 53 _markerTextIsValue(false),
54 indicatorTextFont("Arial", 10, QFont::Normal) // Previously we just did the indicator text in 'default' font 54 indicatorTextFont("Arial", 10, QFont::Normal) // Previously we just did the indicator text in 'default' font
55 { 55 {
56 // Ensure this->heightInPixels is properly initialised 56 // Fixed minimum size.
57 // this->recalculateHeightInPixels(); 57 this->setMinimumSize(60, 20);
58 58 this->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed );
59 // In principle we want to set our min/max sizes etc here. However, if, say, a maximumSize property has been set 59
60 // for this object in a Designer UI File (eg ui/mainWindow.ui) then that setting will override this one, because it 60 // There no particular reason to limit our horizontal size, so, in principle, this call asks that there be no such
61 // will be applied later (in fact pretty much straight after this constructor returns). So we also make this call 61 // (practical) limit.
62 // inside setValue(), which will be invoked _after_ the setter calls that were auto-generated from the Designer UI 62 this->setMaximumWidth(QWIDGETSIZE_MAX);
63 // File. 63
64 this->setSizes(); 64 // Generate mouse move events whenever mouse movers over widget.
65 65 this->setMouseTracking(true);
66 // Generate mouse move events whenever mouse movers over widget. 66
67 this->setMouseTracking(true); 67 this->repaint();
68 68 }
69 this->repaint(); 69
70 }
71 70
72 /** 71 /**
73 * @brief Set the normal limits in the _prexXxx values and calculate 72 * @brief Set the normal limits in the _prexXxx values and calculate
74 * the real drawing limits so that we can see if a value is slightly 73 * the real drawing limits so that we can see if a value is slightly
75 * out of range. 74 * out of range.
108 _markerText = QString("%1").arg(value, 0, 'f', _prec); 107 _markerText = QString("%1").arg(value, 0, 'f', _prec);
109 qDebug() << _markerText; 108 qDebug() << _markerText;
110 } 109 }
111 110
112 update(); 111 update();
113
114 // See comment in constructor for why we call this here
115 //this->setSizes();
116 return; 112 return;
117 } 113 }
118 114
119 115
120 void RangedSlider::setPrecision(int precision) 116 void RangedSlider::setPrecision(int precision)
147 { 143 {
148 _markerTextIsValue = val; 144 _markerTextIsValue = val;
149 update(); 145 update();
150 } 146 }
151 147
152
153 void RangedSlider::recalculateHeightInPixels() const {
154 //
155 // We need to be able to tell Qt about our minimum and preferred size in pixels. This is something that's going
156 // to depend on the dots-per-inch (DPI) resolution of the monitor we're being displayed on. Advice at
157 // https://doc.qt.io/qt-5/highdpi.html is that, for best High DPI display support, we should replace hard-coded
158 // sizes in layouts and drawing code with values calculated from font metrics or screen size. For this widget, we
159 // use font sizes (as described in more detail later in this comment) as it seems simpler and the height of the
160 // widget really is determined by the size of the text it contains.
161 //
162 // In theory, someone might be running the app on a system with multiple screens with different DPI resolutions,
163 // so, in principle we ought to do redo size calculations every time the widget is moved, in case it moves from one
164 // screen to another and the resolution changes. In practice, I'm not sure how big a requirement this is. So, for
165 // now, have just tried to organise things so that it would, in principle, be possible to implement such behaviour
166 // in future.
167 //
168 // We want height to be fixed, as the slider does not get more readable if you make it taller. So minimum and
169 // preferred height are the same.
170 //
171 // For width, We are OK for them to expand and contract horizontally, within reason, as the size of the main window
172 // changes. Minimum and preferred widths are a bit of a rule-of-thumb, but 2× and 4× height are a sensible stab.
173 //
174 // Firstly we have to determine what the fixed height is. We could query the DPI resolution and size of the current
175 // screen, but the simplest thing is to use font sizes. The slider is basically two lines of characters high. Top
176 // line is the "indicator" text that sits above the slider visual in the middle of the "preferred range". Bottom
177 // line is the slider visual and the "value" text that sits to the right of the slider visual. The fonts for both
178 // bits of text are set in device-independent points in the constructor, and we can just query their height etc in
179 // pixels.
180 //
181 // Secondly, the way we tell Qt about minimum and preferred sizes is slightly different:
182 // • setMinimumSize() tells Qt not to make us smaller than the specified size when resizing windows etc, HOWEVER
183 // it does not determine what size we are initially drawn
184 // • instead, Qt calls sizeHint() when doing initial layout, and we must override this to supply our desired
185 // initial dimensions. NB: Although it makes no sense, there is nothing to stop this method returning dimensions
186 // below the minimums already set via setMinimumSize(). (AIUI, sizeHint() is also called on resize events to
187 // find our preferred dimensions.)
188 //
189 // The final wrinkle is that the height of the font sort of depends what you mean. Strictly, using the inter-line
190 // spacing (= height plus leading, though the latter is often 0) gives you enough space to show any character of the
191 // font. It is helpful for the indicator text to have a bit of space below it before we draw the graphical bit, and
192 // it's not a large font in any case. However, for large value text font we don't necessarily need all this space
193 // because we currently only show digits and decimal points, which don't require space below the baseline. However,
194 // assumptions about space below the baseline are locale-specific, so, say, using ascent() instead of lineSpacing()
195 // could end up painting us into a corner.
196 //
197 //QFontMetrics indicatorTextFontMetrics(this->indicatorTextFont);
198 // this->heightInPixels = this->height();
199 return;
200 }
201
202 void RangedSlider::setSizes() {
203 // Fixed minimum size.
204 this->setMinimumSize(60, 20);
205 this->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed );
206
207 // There no particular reason to limit our horizontal size, so, in principle, this call asks that there be no such
208 // (practical) limit.
209 this->setMaximumWidth(QWIDGETSIZE_MAX);
210
211 return;
212 }
213
214 //QSize RangedSlider::sizeHint() const
215 //{
216 // this->recalculateHeightInPixels();
217 // return QSize(4 * this->heightInPixels, this->heightInPixels);
218 //}
219 148
220 void RangedSlider::mouseMoveEvent(QMouseEvent* event) 149 void RangedSlider::mouseMoveEvent(QMouseEvent* event)
221 { 150 {
222 event->accept(); 151 event->accept();
223 152
329 258
330 return; 259 return;
331 } 260 }
332 261
333 262
334 void RangedSlider::moveEvent(QMoveEvent *event) { 263 void RangedSlider::moveEvent(QMoveEvent *event)
335 // If we've moved, we might be on a new screen with a different DPI resolution... 264 {
336 // .:TBD:. This almost certainly needs further work and further testing. It's far from clear whether our font size 265 QWidget::moveEvent(event);
337 // querying will give different answers just because the app has been moved from one screen to another. 266 return;
338 this->recalculateHeightInPixels(); 267 }
339
340 QWidget::moveEvent(event);
341 return;
342 }

mercurial