Qt編寫自定義控件54-時鐘儀表盤

1、前言

這個控件沒有太多的應用場景,主要就是練手,論美觀的話比不上以前發過的一個圖片時鐘控件,因此此控件也是做爲一個基礎的繪製demo出如今Qt源碼中,咱們能夠在Qt的安裝目錄下找到一個時鐘控件的繪製,甚至還有qml版本,本控件無非就是一個儀表邊框加上時鐘分鐘刻度再加上時分秒指針,打完收工,我是在此基礎上增長了能夠設置各類顏色,而後鼠標右鍵可設置四種效果 普通效果/彈簧效果/連續效果/隱藏效果,彈簧效果的意思是秒鐘走動的時候,先移動到超過指定位置,而後又從新彈回來,連續效果的意思是將步長減小,一點點的移動,將秒鐘的定時器精度調高。還有一個新增的功能是內置了設置系統時間公共槽函數,支持任意操做系統。linux

2、實現的功能

  • 1:可設置邊框顏色
  • 2:可設置前景色背景色
  • 3:可設置時鐘分鐘秒鐘指針顏色
  • 4:可設置刷新間隔
  • 5:鼠標右鍵可設置四種效果 普通效果/彈簧效果/連續效果/隱藏效果
  • 6:增長設置系統時間公共槽函數,支持任意操做系統

3、效果圖

4、頭文件代碼

#ifndef GAUGECLOCK_H
#define GAUGECLOCK_H

/**
 * 時鐘儀表盤控件 做者:feiyangqingyun(QQ:517216493) 2016-10-23
 * 1:可設置邊框顏色
 * 2:可設置前景色背景色
 * 3:可設置時鐘分鐘秒鐘指針顏色
 * 4:可設置刷新間隔
 * 5:鼠標右鍵可設置四種效果 普通效果/彈簧效果/連續效果/隱藏效果
 * 6:增長設置系統時間公共槽函數,支持任意操做系統
 */

#include <QWidget>

#ifdef quc
#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
#include <QtDesigner/QDesignerExportWidget>
#else
#include <QtUiPlugin/QDesignerExportWidget>
#endif

class QDESIGNER_WIDGET_EXPORT GaugeClock : public QWidget
#else
class GaugeClock : public QWidget
#endif

{
	Q_OBJECT
	Q_ENUMS(SecondStyle)

	Q_PROPERTY(QColor crownColorStart READ getCrownColorStart WRITE setCrownColorStart)
	Q_PROPERTY(QColor crownColorEnd READ getCrownColorEnd WRITE setCrownColorEnd)

	Q_PROPERTY(QColor foreground READ getForeground WRITE setForeground)
	Q_PROPERTY(QColor background READ getBackground WRITE setBackground)

	Q_PROPERTY(QColor pointerHourColor READ getPointerHourColor WRITE setPointerHourColor)
	Q_PROPERTY(QColor pointerMinColor READ getPointerMinColor WRITE setPointerMinColor)
	Q_PROPERTY(QColor pointerSecColor READ getPointerSecColor WRITE setPointerSecColor)

    Q_PROPERTY(SecondStyle secondStyle READ getSecondStyle WRITE setSecondStyle)

public:
	enum SecondStyle {
		SecondStyle_Normal = 0,     //普通效果
		SecondStyle_Spring = 1,     //彈簧效果
		SecondStyle_Continue = 2,   //連續效果
		SecondStyle_Hide = 3        //隱藏效果
	};

	explicit GaugeClock(QWidget *parent = 0);
	~GaugeClock();

protected:
	void paintEvent(QPaintEvent *);
	void drawCrown(QPainter *painter);
	void drawBg(QPainter *painter);
	void drawScale(QPainter *painter);
	void drawScaleNum(QPainter *painter);
	void drawHour(QPainter *painter);
	void drawMin(QPainter *painter);
	void drawSec(QPainter *painter);
	void drawDot(QPainter *painter);

private:
    QColor crownColorStart;         //外邊框漸變開始顏色
	QColor crownColorEnd;           //外邊框漸變結束顏色

	QColor foreground;              //前景色
	QColor background;              //背景色

	QColor pointerHourColor;        //時鐘指針顏色
	QColor pointerMinColor;         //分鐘指針顏色
	QColor pointerSecColor;         //秒鐘指針顏色

    SecondStyle secondStyle;        //秒針走動樣式

	QTimer *timer;                  //定時器繪製
	int hour, min, sec, msec;       //時分秒毫秒

	QTimer *timerSpring;            //定時器顯示彈簧效果
	double angleSpring;             //彈簧角度

	QAction *action_secondstyle;    //秒針樣式右鍵菜單

private slots:
	void doAction();
	void updateTime();
	void updateSpring();

public:
	SecondStyle getSecondStyle()    const;

	QColor getCrownColorStart()     const;
	QColor getCrownColorEnd()       const;

	QColor getForeground()          const;
	QColor getBackground()          const;

	QColor getPointerHourColor()    const;
	QColor getPointerMinColor()     const;
	QColor getPointerSecColor()     const;

	QSize sizeHint()                const;
	QSize minimumSizeHint()         const;

public Q_SLOTS:
	//設置秒針走動樣式
    void setSecondStyle(const SecondStyle &secondStyle);
	//設置系統時間
    void setSystemDateTime(const QString &year, const QString &month, const QString &day,
                           const QString &hour, const QString &min, const QString &sec);

	//設置外邊框漸變顏色
    void setCrownColorStart(const QColor &crownColorStart);
    void setCrownColorEnd(const QColor &crownColorEnd);

	//設置前景色
    void setForeground(const QColor &foreground);
	//設備背景色
    void setBackground(const QColor &background);

	//設置時鐘指針顏色
    void setPointerHourColor(const QColor &pointerHourColor);
	//設置分鐘指針顏色
    void setPointerMinColor(const QColor &pointerMinColor);
	//設置秒鐘指針顏色
    void setPointerSecColor(const QColor &pointerSecColor);
};

#endif // GAUGECLOCK_H

5、核心代碼

void GaugeClock::paintEvent(QPaintEvent *)
{
    int width = this->width();
    int height = this->height();
    int side = qMin(width, height);

    //繪製準備工做,啓用反鋸齒,平移座標軸中心,等比例縮放
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
    painter.translate(width / 2, height / 2);    
    painter.scale(side / 200.0, side / 200.0);

    //繪製外邊框
    drawCrown(&painter);
    //繪製背景
    drawBg(&painter);
    //繪製刻度線
    drawScale(&painter);
    //繪製刻度值
    drawScaleNum(&painter);
    //繪製時鐘指針
    drawHour(&painter);
    //繪製分鐘指針
    drawMin(&painter);
    //繪製秒鐘指針
    drawSec(&painter);
    //繪製中心蓋板
    drawDot(&painter);
}

void GaugeClock::drawCrown(QPainter *painter)
{
    int radius = 99;
    painter->save();
    painter->setPen(Qt::NoPen);
    QLinearGradient crownGradient(0, -radius, 0, radius);
    crownGradient.setColorAt(0, crownColorStart);
    crownGradient.setColorAt(1, crownColorEnd);
    painter->setBrush(crownGradient);
    painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
    painter->restore();
}

void GaugeClock::drawBg(QPainter *painter)
{
    int radius = 92;
    painter->save();
    painter->setPen(Qt::NoPen);
    painter->setBrush(background);
    painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
    painter->restore();
}

void GaugeClock::drawScale(QPainter *painter)
{
    int radius = 90;
    painter->save();

    QPen pen;
    pen.setColor(foreground);
    pen.setCapStyle(Qt::RoundCap);

    for (int i = 0; i <= 60; i++) {
        if (i % 5 == 0) {
            pen.setWidthF(1.5);
            painter->setPen(pen);
            painter->drawLine(0, radius - 10, 0, radius);
        } else {
            pen.setWidthF(0.5);
            painter->setPen(pen);
            painter->drawLine(0, radius - 5, 0, radius);
        }

        painter->rotate(6);
    }

    painter->restore();
}

void GaugeClock::drawScaleNum(QPainter *painter)
{
    int radius = 70;
    painter->save();
    painter->setPen(foreground);

    double startRad = 60 * (M_PI / 180);
    double deltaRad = 30 * (M_PI / 180);

    for (int i = 0; i < 12; i++) {
        double sina = qSin(startRad - i * deltaRad);
        double cosa = qCos(startRad - i * deltaRad);
        QString strValue = QString("%1").arg(i + 1);

        double textWidth = fontMetrics().width(strValue);
        double textHeight = fontMetrics().height();
        int x = radius * cosa - textWidth / 2;
        int y = -radius * sina + textHeight / 4;
        painter->drawText(x, y, strValue);
    }

    painter->restore();
}

void GaugeClock::drawHour(QPainter *painter)
{
    painter->save();

    //設置畫筆平滑圓角
    QPen pen;
    pen.setCapStyle(Qt::RoundCap);
    painter->setPen(pointerHourColor);
    painter->setBrush(pointerHourColor);

    QPolygon pts;
    pts.setPoints(4, -3, 8, 3, 8, 2, -40, -2, -40);    

    painter->rotate(30.0 * ((hour + min / 60.0)));    
    painter->drawConvexPolygon(pts);

    painter->restore();
}

void GaugeClock::drawMin(QPainter *painter)
{
    painter->save();

    //設置畫筆平滑圓角
    QPen pen;
    pen.setCapStyle(Qt::RoundCap);
    painter->setPen(pointerMinColor);
    painter->setBrush(pointerMinColor);

    QPolygon pts;
    pts.setPoints(4, -2, 8, 2, 8, 1, -60, -1, -60);

    painter->rotate(6.0 * (min + sec / 60.0));    
    painter->drawConvexPolygon(pts);

    painter->restore();
}

void GaugeClock::drawSec(QPainter *painter)
{
    if (secondStyle == SecondStyle_Hide) {
        return;
    }

    painter->save();

    //設置畫筆平滑圓角
    QPen pen;
    pen.setCapStyle(Qt::RoundCap);
    painter->setPen(pointerSecColor);
    painter->setBrush(pointerSecColor);

    QPolygon pts;
    pts.setPoints(3, -1, 10, 1, 10, 0, -70);

    painter->rotate(angleSpring);
    painter->drawConvexPolygon(pts);

    painter->restore();
}

void GaugeClock::drawDot(QPainter *painter)
{
    painter->save();
    QConicalGradient coneGradient(0, 0, -90.0);
    coneGradient.setColorAt(0.0, background);
    coneGradient.setColorAt(0.5, foreground);
    coneGradient.setColorAt(1.0, background);
    painter->setOpacity(0.9);
    painter->setPen(Qt::NoPen);
    painter->setBrush(coneGradient);
    painter->drawEllipse(-5, -5, 10, 10);
    painter->restore();
}

void GaugeClock::doAction()
{
    QAction *action = (QAction *)sender();
    QString str = action->text();

    if (str == "彈簧效果") {
        action->setText("連續效果");
        setSecondStyle(SecondStyle_Spring);
    } else if (str == "連續效果") {
        action->setText("隱藏效果");
        setSecondStyle(SecondStyle_Continue);
    } else if (str == "隱藏效果") {
        action->setText("普通效果");
        setSecondStyle(SecondStyle_Hide);
    } else if (str == "普通效果") {
        action->setText("彈簧效果");
        setSecondStyle(SecondStyle_Normal);
    }
}

6、控件介紹

  1. 超過150個精美控件,涵蓋了各類儀表盤、進度條、進度球、指南針、曲線圖、標尺、溫度計、導航條、導航欄,flatui、高亮按鈕、滑動選擇器、農曆等。遠超qwt集成的控件數量。
  2. 每一個類均可以獨立成一個單獨的控件,零耦合,每一個控件一個頭文件和一個實現文件,不依賴其餘文件,方便單個控件以源碼形式集成到項目中,較少代碼量。qwt的控件類環環相扣,高度耦合,想要使用其中一個控件,必須包含全部的代碼。
  3. 所有純Qt編寫,QWidget+QPainter繪製,支持Qt4.6到Qt5.13的任何Qt版本,支持mingw、msvc、gcc等編譯器,支持任意操做系統好比windows+linux+mac+嵌入式linux等,不亂碼,可直接集成到Qt Creator中,和自帶的控件同樣使用,大部分效果只要設置幾個屬性便可,極爲方便。
  4. 每一個控件都有一個對應的單獨的包含該控件源碼的DEMO,方便參考使用。同時還提供一個全部控件使用的集成的DEMO。
  5. 每一個控件的源代碼都有詳細中文註釋,都按照統一設計規範編寫,方便學習自定義控件的編寫。
  6. 每一個控件默認配色和demo對應的配色都很是精美。
  7. 超過130個可見控件,6個不可見控件。
  8. 部分控件提供多種樣式風格選擇,多種指示器樣式選擇。
  9. 全部控件自適應窗體拉伸變化。
  10. 集成自定義控件屬性設計器,支持拖曳設計,所見即所得,支持導入導出xml格式。
  11. 自帶activex控件demo,全部控件能夠直接運行在ie瀏覽器中。
  12. 集成fontawesome圖形字體+阿里巴巴iconfont收藏的幾百個圖形字體,享受圖形字體帶來的樂趣。
  13. 全部控件最後生成一個動態庫文件(dll或者so等),能夠直接集成到qtcreator中拖曳設計使用。
  14. 目前已經有qml版本,後期會考慮出pyqt版本,若是用戶需求量很大的話。
  15. 自定義控件插件開放動態庫使用(永久免費),無任何後門和限制,請放心使用。
  16. 目前已提供26個版本的dll,其中包括了qt5.12.3 msvc2017 32+64 mingw 32+64 的。
  17. 不按期增長控件和完善控件,不按期更新SDK,歡迎各位提出建議,謝謝!
  18. Qt入門書籍推薦霍亞飛的《Qt Creator快速入門》《Qt5編程入門》,Qt進階書籍推薦官方的《C++ GUI Qt4編程》。
  19. 強烈推薦程序員自我修養和規劃系列書《大話程序員》《程序員的成長課》《解憂程序員》,受益不淺,受益終生!
  20. SDK下載連接:https://pan.baidu.com/s/1A5Gd77kExm8Co5ckT51vvQ 提取碼:877p
相關文章
相關標籤/搜索