一、前言
随着移動網際網路的盛行,現在手機APP大行其道,每個人的手機沒有十幾個APP都不好意思說自己是現代人,各種聊天、購物、直播、小視訊等APP,有個陌生人社交的APP叫探探,本人用過幾次,當然不是去為了找對象,而是純粹為了好玩研究下他的U設計和軟體邏輯流程等,其中有個雷達控件,單擊以後可以搜尋附近的異性進行配對,這個雷達控件的效果蠻好的,于是手癢琢磨着用Qt來實作一個,畢竟自己寫了150多個控件了,已經上瘾了,對各種效果都如魚得水,看到各種效果都不自然的想到編碼思路等。
這個控件的核心其實就是外圍的那個掃描圈和發散的掃描線,中間變大變小恢複正常的圓形頭像,外圍的掃描圈采用錐形漸變顔色,通過透明度控制形成掃描效果,核心方法就是drawPie,至于擴散圈,需要識别到單擊以後将擴散圈存入隊列,因為可能會單擊多次,産生多個擴散圈,至于中間頭像的動态效果,采用三個QPropertyAnimation來實作,一個負責變大,一個負責變小,一個負責恢複正常,然後三個動畫加入到QSequentialAnimationGroup動畫序列中,按照順序執行。
二、實作的功能
- 1:可設定中間圖像
- 2:可設定圖像的邊框寬度+邊框顔色,産生圓形圖像效果
- 3:可設定掃描線的最大半徑
- 4:可設定掃描線的邊框寬度
- 5:可設定擴散圈的線條寬度
- 6:可設定掃描線的每次移動的步長
- 7:可設定擴散圈的每次移動的步長
- 8:可設定掃描線的顔色
- 9:可設定擴散圈的顔色
三、效果圖
四、頭檔案代碼
#ifndef SCANTANTAN_H
#define SCANTANTAN_H
/**
* 探探雷達控件 作者:東門吹雪(QQ:709102202) 整理:feiyangqingyun(QQ:517216493) 2019-10-01
* 1:可設定中間圖像
* 2:可設定圖像的邊框寬度+邊框顔色,産生圓形圖像效果
* 3:可設定掃描線的最大半徑
* 4:可設定掃描線的邊框寬度
* 5:可設定擴散圈的線條寬度
* 6:可設定掃描線的每次移動的步長
* 7:可設定擴散圈的每次移動的步長
* 8:可設定掃描線的顔色
* 9:可設定擴散圈的顔色
*/
#include <QWidget>
class QSequentialAnimationGroup;
#ifdef quc
#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
#include <QtDesigner/QDesignerExportWidget>
#else
#include <QtUiPlugin/QDesignerExportWidget>
#endif
class QDESIGNER_WIDGET_EXPORT ScanTanTan : public QWidget
#else
class ScanTanTan : public QWidget
#endif
{
Q_OBJECT
Q_PROPERTY(QPixmap image READ getImage WRITE setImage)
Q_PROPERTY(int imageBorderWidth READ getImageBorderWidth WRITE setImageBorderWidth)
Q_PROPERTY(QColor imageBorderColor READ getImageBorderColor WRITE setImageBorderColor)
Q_PROPERTY(int scanRadius READ getScanRadius WRITE setScanRadius)
Q_PROPERTY(int scanWidth READ getScanWidth WRITE setScanWidth)
Q_PROPERTY(int ringWidth READ getRingWidth WRITE setRingWidth)
Q_PROPERTY(int scanStep READ getScanStep WRITE setScanStep)
Q_PROPERTY(int ringStep READ getRingStep WRITE setRingStep)
Q_PROPERTY(QColor scanColor READ getScanColor WRITE setScanColor)
Q_PROPERTY(QColor ringColor READ getRingColor WRITE setRingColor)
public:
struct RingData {
int radius; //半徑
float width; //畫筆粗細
int alpha; //透明度
};
explicit ScanTanTan(QWidget *parent = 0);
protected:
void mousePressEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *);
void paintEvent(QPaintEvent *);
void drawScan(QPainter *painter);
void drawRing(QPainter *painter);
void drawImage(QPainter *painter);
private slots:
void changeScan();
void changeRing();
void updateImage(const QVariant &value);
double twoPtDistance(const QPointF &pt1, const QPointF &pt2);
private:
QPixmap image; //中間圖檔
int imageBorderWidth; //圖檔邊框寬度
QColor imageBorderColor;//圖檔邊框顔色
int scanRadius; //掃描線最大半徑
int scanWidth; //掃描線邊框寬度
int ringWidth; //擴散圈線條寬度
int scanStep; //掃描線每次移動的步長
int ringStep; //擴散圈每次移動的步長
QColor scanColor; //掃描線顔色
QColor ringColor; //擴散圈顔色
bool isPressed; //滑鼠是否按下
int ringRadius; //擴散圈半徑
int imageRadius; //圖檔半徑
int scanDeg; //目前掃描線角度
//擴散圈集合,滑鼠可能按下多次則産生多個擴散圈,用隊列存起來
QList<RingData> rings;
//動畫組合,用于中間圖檔的變大放小
QSequentialAnimationGroup *animationGroup;
public:
QPixmap getImage() const;
int getImageBorderWidth() const;
QColor getImageBorderColor()const;
int getScanRadius() const;
int getScanWidth() const;
int getRingWidth() const;
int getScanStep() const;
int getRingStep() const;
QColor getScanColor() const;
QColor getRingColor() const;
QSize sizeHint() const;
QSize minimumSizeHint() const;
public Q_SLOTS:
//設定圖檔+圖檔邊框寬度+圖檔邊框顔色
void setImage(const QPixmap &image);
void setImageBorderWidth(int imageBorderWidth);
void setImageBorderColor(const QColor &imageBorderColor);
//設定掃描線最大半徑+掃描線邊框寬度+擴散圈線條寬度
void setScanRadius(int scanRadius);
void setScanWidth(int scanWidth);
void setRingWidth(int ringWidth);
//設定掃描線步長+擴散圈步長
void setScanStep(int scanStep);
void setRingStep(int ringStep);
//設定掃描線顔色+擴散圈顔色
void setScanColor(const QColor &scanColor);
void setRingColor(const QColor &ringColor);
};
#endif // SCANTANTAN_H
五、核心代碼
void ScanTanTan::paintEvent(QPaintEvent *)
{
int width = this->width();
int height = this->height();
int side = qMin(width, height);
//繪制準備工作,啟用反鋸齒,平移坐标軸中心,等比例縮放
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
painter.translate(width / 2, height / 2);
painter.scale(side / 200.0, side / 200.0);
//繪制掃描線
drawScan(&painter);
//繪制擴散圈
drawRing(&painter);
//繪制中間圖檔
drawImage(&painter);
}
void ScanTanTan::drawScan(QPainter *painter)
{
painter->save();
//錐形漸變顔色,通過透明度控制形成掃描效果
QConicalGradient conicalGradient(0, 0, scanDeg);
QColor color = scanColor;
color.setAlpha(50);
conicalGradient.setColorAt(0, color);
color.setAlpha(0);
conicalGradient.setColorAt(1, color);
//設定畫筆畫刷
QPen pen;
pen.setWidth(scanWidth);
pen.setBrush(conicalGradient);
painter->setPen(pen);
painter->setBrush(conicalGradient);
//繪制餅圓
QRect rect(-scanRadius, -scanRadius, scanRadius * 2, scanRadius * 2);
painter->drawPie(rect, scanDeg * 16, 360 * 16);
painter->restore();
}
void ScanTanTan::drawRing(QPainter *painter)
{
painter->save();
painter->setBrush(Qt::NoBrush);
//繪制所有擴散圈,擴散圈其實就是個沒有背景顔色的圓形
for (int i = 0; i < rings.count(); i++) {
RingData ring = rings.at(i);
int radius = ring.radius;
float width = ring.width;
int alpha = 255 - ring.alpha;
QColor color = ringColor;
color.setAlpha(alpha);
QPen pen;
pen.setWidthF(width);
pen.setColor(color);
painter->setPen(pen);
painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
}
painter->restore();
}
void ScanTanTan::drawImage(QPainter *painter)
{
painter->save();
//設定圓形遮罩路徑,産生圓形頭像效果
QPainterPath path;
path.addEllipse(QPoint(0, 0), imageRadius, imageRadius);
painter->setClipPath(path);
//繪制圖檔
QRect rect(-imageRadius, -imageRadius, imageRadius * 2, imageRadius * 2);
painter->drawPixmap(rect, image);
//繪制圖檔邊緣圓形
QPen pen;
pen.setWidth(imageBorderWidth);
pen.setColor(imageBorderColor);
painter->setPen(pen);
painter->setBrush(Qt::NoBrush);
//以下兩種方法二選一,其實繪制360度的圓弧=繪制無背景的圓形
//painter->drawArc(rect, 0, 360 * 16);
painter->drawEllipse(rect);
painter->restore();
}
六、控件介紹
- 超過160個精美控件,涵蓋了各種儀表盤、進度條、進度球、指南針、曲線圖、标尺、溫度計、導覽列、導航欄,flatui、高亮按鈕、滑動選擇器、農曆等。遠超qwt內建的控件數量。
- 每個類都可以獨立成一個單獨的控件,零耦合,每個控件一個頭檔案和一個實作檔案,不依賴其他檔案,友善單個控件以源碼形式內建到項目中,較少代碼量。qwt的控件類環環相扣,高度耦合,想要使用其中一個控件,必須包含所有的代碼。
- 全部純Qt編寫,QWidget+QPainter繪制,支援Qt4.6到Qt5.13的任何Qt版本,支援mingw、msvc、gcc等編譯器,支援任意作業系統比如windows+linux+mac+嵌入式linux等,不亂碼,可直接內建到Qt Creator中,和自帶的控件一樣使用,大部分效果隻要設定幾個屬性即可,極為友善。
- 每個控件都有一個對應的單獨的包含該控件源碼的DEMO,友善參考使用。同時還提供一個所有控件使用的內建的DEMO。
- 每個控件的源代碼都有詳細中文注釋,都按照統一設計規範編寫,友善學習自定義控件的編寫。
- 每個控件預設配色和demo對應的配色都非常精美。
- 超過130個可見控件,6個不可見控件。
- 部分控件提供多種樣式風格選擇,多種訓示器樣式選擇。
- 所有控件自适應窗體拉伸變化。
- 內建自定義控件屬性設計器,支援拖曳設計,所見即所得,支援導入導出xml格式。
- 自帶activex控件demo,所有控件可以直接運作在ie浏覽器中。
- 內建fontawesome圖形字型+阿裡巴巴iconfont收藏的幾百個圖形字型,享受圖形字型帶來的樂趣。
- 所有控件最後生成一個動态庫檔案(dll或者so等),可以直接內建到qtcreator中拖曳設計使用。
- 目前已經有qml版本,後期會考慮出pyqt版本,如果使用者需求量很大的話。
- 自定義控件插件開放動态庫使用(永久免費),無任何後門和限制,請放心使用。
- 目前已提供26個版本的dll,其中包括了qt5.12.3 msvc2017 32+64 mingw 32+64 的。
- 不定期增加控件和完善控件,不定期更新SDK,歡迎各位提出建議,謝謝!
- Qt入門書籍推薦霍亞飛的《Qt Creator快速入門》《Qt5程式設計入門》,Qt進階書籍推薦官方的《C++ GUI Qt4程式設計》。
- 強烈推薦程式員自我修養和規劃系列書《大話程式員》《程式員的成長課》《解憂程式員》,受益匪淺,受益終生!
- SDK位址: https://gitee.com/feiyangqingyun/QUCSDK