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