Qt編寫自定義控件一開關按鈕

從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
View Code

 

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();
}
View Code

 

此自定義控件集成在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圖表的交互使用。

相關文章
相關標籤/搜索