從2010年進入互聯網+智能手機時代以來,各類各樣的APP大行其道,手機上面的APP有不少流行的元素,開關按鈕我的很是喜歡,手機QQ、360衛士、金山毒霸等,都有不少開關控制一些操做,在Qt widgets應用項目上,在項目中應用些相似的開關按鈕,估計也會爲項目增添很多新鮮感。數據庫
總結了大部分的開關按鈕控件,基本上有兩大類,第一類是純代碼繪製,這種對代碼的掌控度要求比較高,可是靈活性比較好。第二類是貼圖,專業的美工作好的各類狀態的背景圖片,只須要用代碼將該圖片畫到界面上便可。爲了可以涵蓋兩大類的開關按鈕,特地將常見的四種類型(圓角矩形/內圓形/外圓形/圖片)都集成到了自定義的開關按鈕中。api
運行效果:網絡
1:純代碼繪製多線程
純代碼繪製開關按鈕,能夠很靈活的設置各類顏色、間隔、文字等,還能夠產生動畫過分的滑動效果。app
產生滑動效果採用定時器繪製的方式,自動計算滑塊的X軸開始座標,當滑塊的X軸開始座標到達滑塊的X軸結束座標時中止定時器。框架
void SwitchButton::updateValue() { if (checked) { if (startX < endX) { startX = startX + step; } else { startX = endX; timer->stop(); } } else { if (startX > endX) { startX = startX - step; } else { startX = endX; timer->stop(); } } update(); }
2:貼圖繪製ide
void SwitchButton::drawImage(QPainter *painter) { painter->save(); QPixmap pix; if (!checked) { pix = QPixmap(imageOff); } else { pix = QPixmap(imageOn); } //自動等比例平滑縮放居中顯示 int targetWidth = pix.width(); int targetHeight = pix.height(); pix = pix.scaled(targetWidth, targetHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation); int pixX = rect().center().x() - targetWidth / 2; int pixY = rect().center().y() - targetHeight / 2; QPoint point(pixX, pixY); painter->drawPixmap(point, pix); painter->restore(); }
有些人說PS一張精美的圖片也不是很容易,須要專業的,這裏推薦一個好方法,讓你也能夠獲取到這些圖片,其實大部分的APP均可以用解壓軟件打開,拓展名改成.zip便可,解壓出來通常裏面都含有絕大部分的圖片,發現絕大部分的APP都喜歡用圖片做爲背景來展現一些效果,而不是原本來本的用代碼一點點繪製。騰訊就是騰訊啊,大公司!人家的美工MM設計的圖片那真的沒得話說,絕對一流,手機QQ每次升級一個版本,我都會下過來將裏面的精美圖片圖標之類的提取出來,以便項目使用。同時還推薦兩個網站:http://www.easyicon.net/ 個人全部項目用到的ico圖標都是這網站上面的。http://www.ui.cn/ 專業的設計師集中營,這裏面成千上萬的精美的設計的圖片,能夠多多參考。佈局
完整代碼: 動畫
switchbutton.h網站
#ifndef SWITCHBUTTON_H #define SWITCHBUTTON_H /** * 做者:feiyangqingyun(QQ:517216493) 2016-11-6 * 1:可設置開關按鈕的樣式 圓角矩形/內圓形/外圓形/圖片 * 2:可設置選中和未選中時的背景顏色 * 3:可設置選中和未選中時的滑塊顏色 * 4:可設置顯示的文本 * 5:可設置滑塊離背景的間隔 * 6:可設置圓角角度 */ #include <QWidget> class QTimer; class SwitchButton: public QWidget { Q_OBJECT public: enum ButtonStyle { ButtonStyle_Rect = 0, //圓角矩形 ButtonStyle_CircleIn = 1, //內圓形 ButtonStyle_CircleOut = 2,//外圓形 ButtonStyle_Image = 3 //圖片 }; SwitchButton(QWidget *parent = 0); ~SwitchButton(); protected: void mousePressEvent(QMouseEvent *); void resizeEvent(QResizeEvent *); void paintEvent(QPaintEvent *); void drawBg(QPainter *painter); void drawSlider(QPainter *painter); void drawText(QPainter *painter); void drawImage(QPainter *painter); private: bool checked; //是否選中 ButtonStyle buttonStyle; //開關按鈕樣式 QColor bgColorOff; //關閉時背景顏色 QColor bgColorOn; //打開時背景顏色 QColor sliderColorOff; //關閉時滑塊顏色 QColor sliderColorOn; //打開時滑塊顏色 QColor textColorOff; //關閉時文本顏色 QColor textColorOn; //打開時文本顏色 QString textOff; //關閉時顯示的文字 QString textOn; //打開時顯示的文字 QString imageOff; //關閉時顯示的圖片 QString imageOn; //打開時顯示的圖片 int space; //滑塊離背景間隔 int rectRadius; //圓角角度 int step; //每次移動的步長 int startX; //滑塊開始X軸座標 int endX; //滑塊結束X軸座標 QTimer *timer; //定時器繪製 private slots: void updateValue(); public: bool getChecked()const { return checked; } ButtonStyle getButtonStyle()const { return buttonStyle; } QColor getBgColorOff()const { return bgColorOff; } QColor getBgColorOn()const { return bgColorOn; } QColor getSliderColorOff()const { return sliderColorOff; } QColor getSliderColorOn()const { return sliderColorOn; } QColor getTextColorOff()const { return textColorOff; } QColor getTextColorOn()const { return textColorOn; } QString getTextOff()const { return textOff; } QString getTextOn()const { return textOn; } QString getImageOff()const { return imageOff; } QString getImageOn()const { return imageOn; } int getSpace()const { return space; } int getRectRadius()const { return rectRadius; } public slots: //設置是否選中 void setChecked(bool checked); //設置風格樣式 void setButtonStyle(ButtonStyle buttonStyle); //設置背景顏色 void setBgColor(QColor bgColorOff, QColor bgColorOn); //設置滑塊顏色 void setSliderColor(QColor sliderColorOff, QColor sliderColorOn); //設置文本顏色 void setTextColor(QColor textColorOff, QColor textColorOn); //設置文本 void setText(QString textOff, QString textOn); //設置背景圖片 void setImage(QString imageOff, QString imageOn); //設置間隔 void setSpace(int space); //設置圓角角度 void setRectRadius(int rectRadius); signals: void checkedChanged(bool checked); }; #endif // SWITCHBUTTON_H
switchbutton.cpp
#include "switchbutton.h" #include "qpainter.h" #include "qevent.h" #include "qtimer.h" #include "qdebug.h" SwitchButton::SwitchButton(QWidget *parent): QWidget(parent) { checked = false; buttonStyle = ButtonStyle_Rect; bgColorOff = QColor(225, 225, 225); bgColorOn = QColor(250, 250, 250); sliderColorOff = QColor(100, 100, 100); sliderColorOn = QColor(100, 184, 255); textColorOff = QColor(255, 255, 255); textColorOn = QColor(10, 10, 10); textOff = ""; textOn = ""; imageOff = ":/image/btncheckoff1.png"; imageOn = ":/image/btncheckon1.png"; space = 2; rectRadius = 5; step = width() / 50; startX = 0; endX = 0; timer = new QTimer(this); timer->setInterval(5); connect(timer, SIGNAL(timeout()), this, SLOT(updateValue())); setFont(QFont("Microsoft Yahei", 10)); } SwitchButton::~SwitchButton() { } void SwitchButton::mousePressEvent(QMouseEvent *) { checked = !checked; emit checkedChanged(checked); //每次移動的步長爲寬度的 50分之一 step = width() / 50; //狀態切換改變後自動計算終點座標 if (checked) { if (buttonStyle == ButtonStyle_Rect) { endX = width() - width() / 2; } else if (buttonStyle == ButtonStyle_CircleIn) { endX = width() - height(); } else if (buttonStyle == ButtonStyle_CircleOut) { endX = width() - height() + space; } } else { endX = 0; } timer->start(); } void SwitchButton::resizeEvent(QResizeEvent *) { //每次移動的步長爲寬度的 50分之一 step = width() / 50; //尺寸大小改變後自動設置起點座標爲終點 if (checked) { if (buttonStyle == ButtonStyle_Rect) { startX = width() - width() / 2; } else if (buttonStyle == ButtonStyle_CircleIn) { startX = width() - height(); } else if (buttonStyle == ButtonStyle_CircleOut) { startX = width() - height() + space; } } else { startX = 0; } update(); } void SwitchButton::paintEvent(QPaintEvent *) { //繪製準備工做,啓用反鋸齒 QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); if (buttonStyle == ButtonStyle_Image) { //繪製圖片 drawImage(&painter); } else { //繪製背景 drawBg(&painter); //繪製滑塊 drawSlider(&painter); //繪製文字 drawText(&painter); } } void SwitchButton::drawBg(QPainter *painter) { painter->save(); painter->setPen(Qt::NoPen); if (!checked) { painter->setBrush(bgColorOff); } else { painter->setBrush(bgColorOn); } if (buttonStyle == ButtonStyle_Rect) { painter->drawRoundedRect(rect(), rectRadius, rectRadius); } else if (buttonStyle == ButtonStyle_CircleIn) { QRect rect(0, 0, width(), height()); //半徑爲高度的一半 int radius = rect.height() / 2; //圓的寬度爲高度 int circleWidth = rect.height(); QPainterPath path; path.moveTo(radius, rect.left()); path.arcTo(QRectF(rect.left(), rect.top(), circleWidth, circleWidth), 90, 180); path.lineTo(rect.width() - radius, rect.height()); path.arcTo(QRectF(rect.width() - rect.height(), rect.top(), circleWidth, circleWidth), 270, 180); path.lineTo(radius, rect.top()); painter->drawPath(path); } else if (buttonStyle == ButtonStyle_CircleOut) { QRect rect(space, space, width() - space * 2, height() - space * 2); painter->drawRoundedRect(rect, rectRadius, rectRadius); } painter->restore(); } void SwitchButton::drawSlider(QPainter *painter) { painter->save(); painter->setPen(Qt::NoPen); if (!checked) { painter->setBrush(sliderColorOff); } else { painter->setBrush(sliderColorOn); } if (buttonStyle == ButtonStyle_Rect) { int sliderWidth = width() / 2 - space * 2; int sliderHeight = height() - space * 2; QRect sliderRect(startX + space, space, sliderWidth , sliderHeight); painter->drawRoundedRect(sliderRect, rectRadius, rectRadius); } else if (buttonStyle == ButtonStyle_CircleIn) { QRect rect(0, 0, width(), height()); int sliderWidth = rect.height() - space * 2; QRect sliderRect(startX + space, space, sliderWidth, sliderWidth); painter->drawEllipse(sliderRect); } else if (buttonStyle == ButtonStyle_CircleOut) { QRect rect(0, 0, width() - space, height() - space); int sliderWidth = rect.height(); QRect sliderRect(startX, space / 2, sliderWidth, sliderWidth); painter->drawEllipse(sliderRect); } painter->restore(); } void SwitchButton::drawText(QPainter *painter) { painter->save(); if (!checked) { painter->setPen(textColorOff); painter->drawText(width() / 2, 0, width() / 2 - space, height(), Qt::AlignCenter, textOff); } else { painter->setPen(textColorOn); painter->drawText(0, 0, width() / 2 + space * 2, height(), Qt::AlignCenter, textOn); } painter->restore(); } void SwitchButton::drawImage(QPainter *painter) { painter->save(); QPixmap pix; if (!checked) { pix = QPixmap(imageOff); } else { pix = QPixmap(imageOn); } //自動等比例平滑縮放居中顯示 int targetWidth = pix.width(); int targetHeight = pix.height(); pix = pix.scaled(targetWidth, targetHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation); int pixX = rect().center().x() - targetWidth / 2; int pixY = rect().center().y() - targetHeight / 2; QPoint point(pixX, pixY); painter->drawPixmap(point, pix); painter->restore(); } void SwitchButton::updateValue() { if (checked) { if (startX < endX) { startX = startX + step; } else { startX = endX; timer->stop(); } } else { if (startX > endX) { startX = startX - step; } else { startX = endX; timer->stop(); } } update(); } void SwitchButton::setChecked(bool checked) { if (this->checked != checked) { this->checked = checked; emit checkedChanged(checked); update(); } } void SwitchButton::setButtonStyle(SwitchButton::ButtonStyle buttonStyle) { this->buttonStyle = buttonStyle; update(); } void SwitchButton::setBgColor(QColor bgColorOff, QColor bgColorOn) { this->bgColorOff = bgColorOff; this->bgColorOn = bgColorOn; update(); } void SwitchButton::setSliderColor(QColor sliderColorOff, QColor sliderColorOn) { this->sliderColorOff = sliderColorOff; this->sliderColorOn = sliderColorOn; update(); } void SwitchButton::setTextColor(QColor textColorOff, QColor textColorOn) { this->textColorOff = textColorOff; this->textColorOn = textColorOn; update(); } void SwitchButton::setText(QString textOff, QString textOn) { this->textOff = textOff; this->textOn = textOn; update(); } void SwitchButton::setImage(QString imageOff, QString imageOn) { this->imageOff = imageOff; this->imageOn = imageOn; update(); } void SwitchButton::setSpace(int space) { this->space = space; update(); } void SwitchButton::setRectRadius(int rectRadius) { this->rectRadius = rectRadius; update(); }
此自定義控件集成在QFramework中。
自定義控件可執行文件下載:http://pan.baidu.com/s/1i5iCfzv
QFramework簡介:
QFramework是一套通用的Qt程序開發框架,集成主界面佈局、各類自定義控件、數據庫處理、excel極速導出、數據打印、串口通訊、網絡通訊、協議解析、全局熱鍵、郵件發送,短信發送,百度地圖調用、ffmpeg+vlc處理等功能,將經常使用的功能封裝成類庫,提供統一直觀的調用接口,方便使用者使用,對應封裝的庫都有對應的demo程序。
QFramework基本功能:
1:支持從4.7.0到5.7.0的任何Qt版本,不受版本限制。用了此框架,不會再有Qt版本不一樣而引發的程序編譯通不過的煩惱。
2:極速導出數據到excel,支持表格數據或者查詢的數據,不依賴任何組件,支持任何excel、wps等表格軟件版本,導出10萬行數據8個字段只須要3秒完成。對導出的表格樣式可自定義主標題和副標題,可對導出的數據按照指定條件紅色突出顯示。
3:數據導出到pdf及打印功能,支持表格數據或者查詢的數據,支持橫向縱向打印,自動分頁。
4:數據分頁dbapi類,只需傳入表格對象,表名,翻頁按鈕便可。無需再寫重複的方法處理翻頁。
5:各類自定義控件,例如開關按鈕、發光按鈕,儀表盤控件、音量控件、溫溼度控件、儀表儀器類控件等。
6:全新超級中英雙拼輸入法,很是適合觸摸設備。
7:全局熱鍵處理。
8:串口熱敏打印機打印。
9:qcustomplot 2D圖形曲線繪製(含鼠標數據跟蹤)。
10:多線程郵件發送,支持多個接收郵箱。
11:多線程短信發送,支持多個接收號碼及長短信。
12:Qffmpeg+Qvlc視頻處理。
13:取字模,字符轉LED數據處理。
14:全局日誌輸出類 applog,可動態掛載和卸載。
15:全局程序控制類 appkey,可控制程序的使用時間、運行時間、設備數量限制等。
16:封裝百度地圖調用接口,支持設備標註、路線查詢、位置顯示等。
17:自動清理程序早期數據類 cleanapi,傳入要清理的數據庫表名,執行間隔,保留的最大記錄數便可。這樣保證了整個系統存儲的都是最新的數據。
18:NTP校時服務程序。
19:全局截圖處理,能夠很方便的直接在ARM上對程序進行截圖。
20:程序存活檢測功能 applive,經過udp通訊實時發送心跳命令,這樣能夠保證程序7*24小時運行,在ARM上可採用 appdog看門狗程序。
21:已運行時間+當前時間+實時CPU使用率+實時內存使用率等。
22:自定義程序主界面底部信息。
23:Echart圖表的交互使用。