switchbutton.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. #pragma execution_character_set("utf-8")
  2. #include "switchbutton.h"
  3. #include "qpainter.h"
  4. #include <QPainterPath>
  5. #include "qevent.h"
  6. #include "qtimer.h"
  7. #include "qdebug.h"
  8. SwitchButton::SwitchButton(QWidget *parent): QWidget(parent)
  9. {
  10. space = 2;
  11. rectRadius = 5;
  12. checked = false;
  13. showText = true;
  14. showCircle = false;
  15. animation = false;
  16. buttonStyle = ButtonStyle_CircleIn;
  17. bgColorOff = QColor(111, 122, 126);
  18. bgColorOn = QColor(21, 156, 119);
  19. sliderColorOff = QColor(255, 255, 255);
  20. sliderColorOn = QColor(255, 255, 255);
  21. textColorOff = QColor(250, 250, 250);
  22. textColorOn = QColor(255, 255, 255);
  23. textOff = "关闭";
  24. textOn = "开启";
  25. step = 0;
  26. startX = 0;
  27. endX = 0;
  28. timer = new QTimer(this);
  29. timer->setInterval(30);
  30. connect(timer, SIGNAL(timeout()), this, SLOT(updateValue()));
  31. }
  32. SwitchButton::~SwitchButton()
  33. {
  34. if (timer->isActive()) {
  35. timer->stop();
  36. }
  37. }
  38. void SwitchButton::mousePressEvent(QMouseEvent *)
  39. {
  40. checked = !checked;
  41. emit checkedChanged(checked);
  42. //每次移动的步长
  43. step = width() / 7;
  44. //状态切换改变后自动计算终点坐标
  45. if (checked) {
  46. if (buttonStyle == ButtonStyle_Rect) {
  47. endX = width() - width() / 2;
  48. } else if (buttonStyle == ButtonStyle_CircleIn) {
  49. endX = width() - height();
  50. } else if (buttonStyle == ButtonStyle_CircleOut) {
  51. endX = width() - height();
  52. }
  53. } else {
  54. endX = 0;
  55. }
  56. if (animation) {
  57. timer->start();
  58. } else {
  59. startX = endX;
  60. this->update();
  61. }
  62. }
  63. void SwitchButton::resizeEvent(QResizeEvent *)
  64. {
  65. //每次移动的步长为宽度的 50分之一
  66. step = width() / 50;
  67. //尺寸大小改变后自动设置起点坐标为终点
  68. if (checked) {
  69. if (buttonStyle == ButtonStyle_Rect) {
  70. startX = width() - width() / 2;
  71. } else if (buttonStyle == ButtonStyle_CircleIn) {
  72. startX = width() - height();
  73. } else if (buttonStyle == ButtonStyle_CircleOut) {
  74. startX = width() - height();
  75. }
  76. } else {
  77. startX = 0;
  78. }
  79. this->update();
  80. }
  81. void SwitchButton::paintEvent(QPaintEvent *)
  82. {
  83. //绘制准备工作,启用反锯齿
  84. QPainter painter(this);
  85. painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
  86. //绘制背景
  87. drawBg(&painter);
  88. //绘制滑块
  89. drawSlider(&painter);
  90. }
  91. void SwitchButton::drawBg(QPainter *painter)
  92. {
  93. painter->save();
  94. painter->setPen(Qt::NoPen);
  95. QColor bgColor = checked ? bgColorOn : bgColorOff;
  96. if (!isEnabled()) {
  97. bgColor.setAlpha(60);
  98. }
  99. painter->setBrush(bgColor);
  100. if (buttonStyle == ButtonStyle_Rect) {
  101. painter->drawRoundedRect(rect(), rectRadius, rectRadius);
  102. } else if (buttonStyle == ButtonStyle_CircleIn) {
  103. QRect rect(0, 0, width(), height());
  104. //半径为高度的一半
  105. int side = qMin(rect.width(), rect.height());
  106. //左侧圆
  107. QPainterPath path1;
  108. path1.addEllipse(rect.x(), rect.y(), side, side);
  109. //右侧圆
  110. QPainterPath path2;
  111. path2.addEllipse(rect.width() - side, rect.y(), side, side);
  112. //中间矩形
  113. QPainterPath path3;
  114. path3.addRect(rect.x() + side / 2, rect.y(), rect.width() - side, rect.height());
  115. QPainterPath path;
  116. path = path3 + path1 + path2;
  117. painter->drawPath(path);
  118. } else if (buttonStyle == ButtonStyle_CircleOut) {
  119. QRect rect(height() / 2, space, width() - height(), height() - space * 2);
  120. painter->drawRoundedRect(rect, rectRadius, rectRadius);
  121. }
  122. if (buttonStyle == ButtonStyle_Rect || buttonStyle == ButtonStyle_CircleIn) {
  123. //绘制文本和小圆,互斥
  124. if (showText) {
  125. int sliderWidth = qMin(width(), height()) - space * 2;
  126. if (buttonStyle == ButtonStyle_Rect) {
  127. sliderWidth = width() / 2 - 5;
  128. } else if (buttonStyle == ButtonStyle_CircleIn) {
  129. sliderWidth -= 5;
  130. }
  131. if (checked) {
  132. QRect textRect(0, 0, width() - sliderWidth, height());
  133. painter->setPen(textColorOn);
  134. painter->drawText(textRect, Qt::AlignCenter, textOn);
  135. } else {
  136. QRect textRect(sliderWidth, 0, width() - sliderWidth, height());
  137. painter->setPen(textColorOff);
  138. painter->drawText(textRect, Qt::AlignCenter, textOff);
  139. }
  140. } else if (showCircle) {
  141. int side = qMin(width(), height()) / 2;
  142. int y = (height() - side) / 2;
  143. if (checked) {
  144. QRect circleRect(side / 2, y, side, side);
  145. QPen pen(textColorOn, 2);
  146. painter->setPen(pen);
  147. painter->setBrush(Qt::NoBrush);
  148. painter->drawEllipse(circleRect);
  149. } else {
  150. QRect circleRect(width() - (side * 1.5), y, side, side);
  151. QPen pen(textColorOff, 2);
  152. painter->setPen(pen);
  153. painter->setBrush(Qt::NoBrush);
  154. painter->drawEllipse(circleRect);
  155. }
  156. }
  157. }
  158. painter->restore();
  159. }
  160. void SwitchButton::drawSlider(QPainter *painter)
  161. {
  162. painter->save();
  163. painter->setPen(Qt::NoPen);
  164. if (!checked) {
  165. painter->setBrush(sliderColorOff);
  166. } else {
  167. painter->setBrush(sliderColorOn);
  168. }
  169. if (buttonStyle == ButtonStyle_Rect) {
  170. int sliderWidth = width() / 2 - space * 2;
  171. int sliderHeight = height() - space * 2;
  172. QRect sliderRect(startX + space, space, sliderWidth , sliderHeight);
  173. painter->drawRoundedRect(sliderRect, rectRadius, rectRadius);
  174. } else if (buttonStyle == ButtonStyle_CircleIn) {
  175. QRect rect(0, 0, width(), height());
  176. int sliderWidth = qMin(rect.width(), rect.height()) - space * 2;
  177. QRect sliderRect(startX + space, space, sliderWidth, sliderWidth);
  178. painter->drawEllipse(sliderRect);
  179. } else if (buttonStyle == ButtonStyle_CircleOut) {
  180. int sliderWidth = this->height();
  181. QRect sliderRect(startX, 0, sliderWidth, sliderWidth);
  182. QColor color1 = (checked ? Qt::white : bgColorOff);
  183. QColor color2 = (checked ? sliderColorOn : sliderColorOff);
  184. QRadialGradient radialGradient(sliderRect.center(), sliderWidth / 2);
  185. radialGradient.setColorAt(0, checked ? color1 : color2);
  186. radialGradient.setColorAt(0.5, checked ? color1 : color2);
  187. radialGradient.setColorAt(0.6, checked ? color2 : color1);
  188. radialGradient.setColorAt(1.0, checked ? color2 : color1);
  189. painter->setBrush(radialGradient);
  190. painter->drawEllipse(sliderRect);
  191. }
  192. painter->restore();
  193. }
  194. void SwitchButton::change()
  195. {
  196. mousePressEvent(NULL);
  197. }
  198. void SwitchButton::updateValue()
  199. {
  200. if (checked) {
  201. if (startX < endX) {
  202. startX = startX + step;
  203. } else {
  204. startX = endX;
  205. timer->stop();
  206. }
  207. } else {
  208. if (startX > endX) {
  209. startX = startX - step;
  210. } else {
  211. startX = endX;
  212. timer->stop();
  213. }
  214. }
  215. this->update();
  216. }
  217. int SwitchButton::getSpace() const
  218. {
  219. return this->space;
  220. }
  221. int SwitchButton::getRectRadius() const
  222. {
  223. return this->rectRadius;
  224. }
  225. bool SwitchButton::getChecked() const
  226. {
  227. return this->checked;
  228. }
  229. bool SwitchButton::getShowText() const
  230. {
  231. return this->showText;
  232. }
  233. bool SwitchButton::getShowCircle() const
  234. {
  235. return this->showCircle;
  236. }
  237. bool SwitchButton::getAnimation() const
  238. {
  239. return this->animation;
  240. }
  241. SwitchButton::ButtonStyle SwitchButton::getButtonStyle() const
  242. {
  243. return this->buttonStyle;
  244. }
  245. QColor SwitchButton::getBgColorOff() const
  246. {
  247. return bgColorOff;
  248. }
  249. QColor SwitchButton::getBgColorOn() const
  250. {
  251. return this->bgColorOn;
  252. }
  253. QColor SwitchButton::getSliderColorOff() const
  254. {
  255. return this->sliderColorOff;
  256. }
  257. QColor SwitchButton::getSliderColorOn() const
  258. {
  259. return this->sliderColorOn;
  260. }
  261. QColor SwitchButton::getTextColorOff() const
  262. {
  263. return this->textColorOff;
  264. }
  265. QColor SwitchButton::getTextColorOn() const
  266. {
  267. return this->textColorOn;
  268. }
  269. QString SwitchButton::getTextOff() const
  270. {
  271. return this->textOff;
  272. }
  273. QString SwitchButton::getTextOn() const
  274. {
  275. return this->textOn;
  276. }
  277. QSize SwitchButton::sizeHint() const
  278. {
  279. return QSize(70, 30);
  280. }
  281. QSize SwitchButton::minimumSizeHint() const
  282. {
  283. return QSize(10, 5);
  284. }
  285. void SwitchButton::setSpace(int space)
  286. {
  287. if (this->space != space) {
  288. this->space = space;
  289. this->update();
  290. }
  291. }
  292. void SwitchButton::setRectRadius(int rectRadius)
  293. {
  294. if (this->rectRadius != rectRadius) {
  295. this->rectRadius = rectRadius;
  296. this->update();
  297. }
  298. }
  299. void SwitchButton::setChecked(bool checked)
  300. {
  301. //如果刚刚初始化完成的属性改变则延时处理
  302. if (this->checked != checked) {
  303. if (step == 0) {
  304. QTimer::singleShot(10, this, SLOT(change()));
  305. } else {
  306. mousePressEvent(NULL);
  307. }
  308. }
  309. }
  310. void SwitchButton::setShowText(bool showText)
  311. {
  312. if (this->showText != showText) {
  313. this->showText = showText;
  314. this->update();
  315. }
  316. }
  317. void SwitchButton::setShowCircle(bool showCircle)
  318. {
  319. if (this->showCircle != showCircle) {
  320. this->showCircle = showCircle;
  321. this->update();
  322. }
  323. }
  324. void SwitchButton::setAnimation(bool animation)
  325. {
  326. if (this->animation != animation) {
  327. this->animation = animation;
  328. this->update();
  329. }
  330. }
  331. void SwitchButton::setButtonStyle(const SwitchButton::ButtonStyle &buttonStyle)
  332. {
  333. if (this->buttonStyle != buttonStyle) {
  334. this->buttonStyle = buttonStyle;
  335. this->update();
  336. }
  337. }
  338. void SwitchButton::setBgColorOff(const QColor &bgColorOff)
  339. {
  340. if (this->bgColorOff != bgColorOff) {
  341. this->bgColorOff = bgColorOff;
  342. this->update();
  343. }
  344. }
  345. void SwitchButton::setBgColorOn(const QColor &bgColorOn)
  346. {
  347. if (this->bgColorOn != bgColorOn) {
  348. this->bgColorOn = bgColorOn;
  349. this->update();
  350. }
  351. }
  352. void SwitchButton::setSliderColorOff(const QColor &sliderColorOff)
  353. {
  354. if (this->sliderColorOff != sliderColorOff) {
  355. this->sliderColorOff = sliderColorOff;
  356. this->update();
  357. }
  358. }
  359. void SwitchButton::setSliderColorOn(const QColor &sliderColorOn)
  360. {
  361. if (this->sliderColorOn != sliderColorOn) {
  362. this->sliderColorOn = sliderColorOn;
  363. this->update();
  364. }
  365. }
  366. void SwitchButton::setTextColorOff(const QColor &textColorOff)
  367. {
  368. if (this->textColorOff != textColorOff) {
  369. this->textColorOff = textColorOff;
  370. this->update();
  371. }
  372. }
  373. void SwitchButton::setTextColorOn(const QColor &textColorOn)
  374. {
  375. if (this->textColorOn != textColorOn) {
  376. this->textColorOn = textColorOn;
  377. this->update();
  378. }
  379. }
  380. void SwitchButton::enableText(bool enable)
  381. {
  382. if (!enable) {
  383. this->textOn = "";
  384. this->textOff = "";
  385. this->update();
  386. }
  387. }
  388. void SwitchButton::setTextOff(const QString &textOff)
  389. {
  390. if (this->textOff != textOff) {
  391. this->textOff = textOff;
  392. this->update();
  393. }
  394. }
  395. void SwitchButton::setTextOn(const QString &textOn)
  396. {
  397. if (this->textOn != textOn) {
  398. this->textOn = textOn;
  399. this->update();
  400. }
  401. }