最近做到一个项目,需要设置一个参数的上下限,最开始考虑的办法是用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 }