Qt DoubleSlider 双滑块支持float变化的控件,以及单滑块float控件

最近做到一个项目,需要设置一个参数的上下限,最开始考虑的办法是用QSlider控件来实现,发现有两个不太合适的地方。

  • 一个参数需要用两个控件来设置,而且两者之间还有大小关系的限制,比较麻烦;
  • QSlider只支持int类型的输入与改变。

因此,决定自己写一个,本着资源共享的精神,特将代码贴出,供大家参考,如有更好的想法,也欢迎指正与交流。

双滑块的代码

 1 #ifndef DOUBLESLIDER_H
 2 #define DOUBLESLIDER_H
 3  
 4 #include 
 5  
 6 class DoubleSlider : public QWidget
 7 {
 8     Q_OBJECT
 9 public:
10     DoubleSlider(QWidget* parent = 0);
11     void setRange(float min, float max);
12     void setSingleStep(float step);
13  
14     enum State{ MinHandle,MaxHandle,None};
15  
16     float minValue() const;
17     float maxValue() const;
18  
19     float minRange() const;
20     float maxRange() const;
21  
22 public slots:
23     void setLabel(const QString& label);
24     void setMaxValue(float val);
25     void setMinValue(float val);
26  
27 signals:
28     void minValueChanged(float);
29     void maxValueChanged(float);
30  
31 private:
32     float m_min;
33     float m_max;
34     float m_singleStep;
35  
36     float m_minValue;
37     float m_maxValue;
38  
39     QRect minHandleRegion;
40     QRect maxHandleRegion;
41  
42     State m_state;
43  
44     QString m_label;
45  
46 protected:
47     void paintEvent(QPaintEvent* event);
48     void paintColoredRect(QRect rect, QColor color, QPainter* painter);
49     void paintValueLabel(QPainter* painter);
50  
51     void mousePressEvent(QMouseEvent* event);
52     void mouseMoveEvent(QMouseEvent* event);
53  
54     void keyPressEvent(QKeyEvent *event);
55     void leaveEvent(QEvent* event);
56  
57 };
58  
59 #endif // DOUBLESLIDER_H
  1 #include "doubleslider.h"
  2 #include 
  3 #include 
  4  
  5 DoubleSlider::DoubleSlider(QWidget* parent)
  6     : QWidget(parent)
  7     , m_min(0.0f)
  8     , m_max(99.0f)
  9     , m_singleStep(0.1f)
 10     , m_minValue(0.0f)
 11     , m_maxValue(99.0f)
 12     , m_state(None)
 13 {
 14     setFixedHeight(50);
 15     setFocusPolicy(Qt::StrongFocus);
 16 }
 17  
 18 void DoubleSlider::paintEvent(QPaintEvent* event)
 19 {
 20     QWidget::paintEvent(event);
 21     QPainter painter(this);
 22     paintValueLabel(&painter);
 23 }
 24  
 25 void DoubleSlider::paintColoredRect(QRect rect, QColor color ,QPainter* painter)
 26 {
 27     painter->fillRect(rect,QBrush(color));
 28 }
 29  
 30 void DoubleSlider::paintValueLabel(QPainter* painter)
 31 {
 32     painter->setBrush(Qt::NoBrush);
 33     painter->setPen(Qt::black);
 34     painter->setFont(QFont("Arial",12));
 35  
 36     QString minValueString = QString::number(m_minValue,'f',3);
 37     QString maxValueString = QString::number(m_maxValue,'f',3);
 38  
 39     QFontMetrics metrics = painter->fontMetrics();
 40     int mintextWidth = metrics.width(minValueString);
 41     int maxtextWidth = metrics.width(maxValueString);
 42     int textHeight = metrics.height();
 43  
 44     //---- paint text
 45     painter->drawText(QRectF(2,4,mintextWidth,textHeight),minValueString);
 46     painter->drawText(QRectF(width() - maxtextWidth -2, 4, maxtextWidth,textHeight), maxValueString);
 47  
 48  
 49     //----- paint label
 50     painter->setFont(QFont("Arial",12));
 51     metrics = painter->fontMetrics();
 52     int labelWidth = metrics.width(m_label);
 53     int labelHeight = metrics.height();
 54  
 55     QRectF textRect = QRectF((width()/2 - labelWidth/2), 0,labelWidth,labelHeight);
 56  
 57     painter->drawText(textRect,m_label);
 58  
 59  
 60     int minPos = ( m_minValue - m_min ) * width() / (m_max - m_min);
 61     int maxPos = (m_maxValue - m_min ) * width() /  (m_max - m_min);
 62  
 63     if(minPos <= 4){
 64         minPos = 4;
 65     }else if(minPos >= width() - 8){
 66         minPos = width() - 8;
 67     }else{}
 68  
 69     if(maxPos <= 4){
 70         maxPos = 4;
 71     }else if(maxPos >= width() -8){
 72         maxPos = width() - 8;
 73     }else{}
 74  
 75  
 76     //----- paint groove
 77     paintColoredRect(QRect(4,37,width() - 8,2),Qt::gray,painter);
 78     paintColoredRect(QRect(minPos + 4,37,maxPos - minPos,2),QColor(51,153,155),painter);
 79  
 80     //----- handle
 81  
 82     minHandleRegion = QRect(minPos ,30,8,16);
 83     maxHandleRegion = QRect(maxPos ,30,8,16);
 84  
 85     //-----paint Handle
 86     QColor minColor  = (m_state == MinHandle) ? QColor(51,153,155) : Qt::darkGray;
 87     QColor maxColor  = (m_state == MaxHandle) ? QColor(51,153,155) : Qt::darkGray;
 88     paintColoredRect(minHandleRegion,minColor,painter);
 89     paintColoredRect(maxHandleRegion,maxColor,painter);
 90 }
 91  
 92 inline float getValidValue(float val, float min, float max)
 93 {
 94     float tmp = std::max(val, min);
 95     return std::min(tmp, max);
 96 }
 97  
 98  
 99 void DoubleSlider::setRange(float min, float max)
100 {
101     m_min = min;
102     m_max = max;
103  
104     if(minValue() < m_min)
105         setMinValue(m_min);
106  
107     if(maxValue() > m_max){
108         setMaxValue(m_max);
109     }
110 }
111  
112 void DoubleSlider::setSingleStep(float step)
113 {
114     m_singleStep = step;
115 }
116  
117 float DoubleSlider::minValue() const
118 {
119     return m_minValue;
120 }
121 void DoubleSlider::setMinValue(float val)
122 {
123     if(fabs( m_minValue - val ) > 0.0001 ){
124         m_minValue = val;
125         emit minValueChanged(val);
126     }
127 }
128  
129 float DoubleSlider::maxValue() const
130 {
131     return m_maxValue;
132 }
133 void DoubleSlider::setMaxValue(float val)
134 {
135     if(fabs(m_maxValue - val) > 0.0001){
136         m_maxValue = val;
137         emit maxValueChanged(val);
138     }
139 }
140  
141 void DoubleSlider::setLabel(const QString& label)
142 {
143    m_label = label;
144    update();
145 }
146  
147 void DoubleSlider::leaveEvent(QEvent* event)
148 {
149     QWidget::leaveEvent(event);
150     m_state = None;
151     update();
152 }
153  
154 float DoubleSlider::minRange() const
155 {
156     return m_min;
157 }
158 float DoubleSlider::maxRange() const
159 {
160     return m_max;
161 }
162  
163  
164 void DoubleSlider::mousePressEvent(QMouseEvent* event)
165 {
166     if(minHandleRegion.contains(event->pos())){
167         m_state = MinHandle;
168     }else if(maxHandleRegion.contains(event->pos())){
169         m_state = MaxHandle;
170     }else{
171         m_state = None;
172     }
173  
174     if(fabs(minValue() - maxValue()) < 0.001){
175         if(fabs(minValue() - m_min) < 0.001){
176             m_state = MaxHandle;
177         }else if(fabs(minValue() - m_max) < 0.001){
178             m_state = MinHandle;
179         }else{}
180     }
181  
182     update();
183 }
184  
185 void DoubleSlider::mouseMoveEvent(QMouseEvent* event)
186 {
187     if(event->buttons() & Qt::LeftButton){
188         float move = event->x() * (m_max - m_min) * 1.0/ width() + m_min;
189  
190         switch(m_state){
191             case MinHandle:{
192                 float val = getValidValue( move, m_min,maxValue());
193                 setMinValue(val);
194                 break;
195             }
196  
197             case MaxHandle:{
198                     float val = getValidValue(move, minValue(), m_max);
199                     setMaxValue(val);
200                     break;
201             }
202             case None:default: break;
203         }
204     }
205     update();
206 }
207  
208  
209 void DoubleSlider::keyPressEvent(QKeyEvent *event)
210 {
211     QWidget::keyPressEvent(event);
212  
213     if(event->key() == Qt::Key_Left){
214         if(m_state == MinHandle){
215             float val = getValidValue(minValue()- m_singleStep, m_min ,maxValue());
216             setMinValue(val);
217         }else if(m_state == MaxHandle) {
218             float val = getValidValue(maxValue()- m_singleStep, minValue() ,m_max);
219             setMaxValue(val);
220         }else{}
221     }else if(event->key() == Qt::Key_Right){
222         if(m_state == MinHandle){
223             float val = getValidValue(minValue() + m_singleStep, m_min ,maxValue());
224             setMinValue(val);
225         }else if(m_state == MaxHandle) {
226             float val = getValidValue(maxValue() + m_singleStep, minValue() ,m_max);
227             setMaxValue(val);
228         }else{}
229     }
230  
231     update();
232  
233 }
原文地址:https://www.cnblogs.com/ybqjymy/p/13813001.html