Qt編寫自定義控制元件51-可輸入儀表盤
阿新 • • 發佈:2019-09-16
一、前言
這個控制元件是近期定製的控制元件,還是比較實用的控制元件之一,使用者主要是提了三點需求,一點是切換焦點的時候控制元件放大突出顯示,一點是可直接輸入或者編輯值,還有一點是支援上下鍵及翻頁鍵和滑鼠滾輪來動態修改值,類似於qspinbox控制元件。要能夠支援直接輸入首先想到的就是qlineedit控制元件,在原有的儀表盤控制元件上中間部分,放置一個qlineedit控制元件用來輸入值,採用正則表示式來限制只能輸入數字,為了使得qlinedit和自定義繪製的儀表盤完全融為一體,必須設定qlineedit的樣式為背景透明,至於輸入框的位置,有個小技巧就是直接將輸入框設定為控制元件的大小,這樣輸入的焦點永遠在控制元件的中間,完全混合,絲毫看不出是一個輸入框控制元件插在那裡,至於上下鍵及翻頁鍵和滑鼠滾輪,直接安裝事件過濾器即可識別到,進行對應的處理即可。
二、實現的功能
- 1:可設定範圍值,支援負數值
- 2:可設定開始旋轉角度/結束旋轉角度
- 3:可設定是否啟用動畫效果以及動畫效果每次移動的步長
- 4:可設定外圓背景/內圓背景/進度顏色/空餘顏色/文字顏色
- 5:自適應窗體拉伸,文字自動縮放
- 6:支援tab及滑鼠按下切換焦點
- 7:支援直接輸入值立即應用
- 8:獲取焦點控制元件自動變大
- 9:支援鍵盤上下鍵步長為1修改值
- 10:支援上下翻頁鍵步長為10修改值
- 11:支援滑鼠滾輪步長為1修改值
三、效果圖
四、標頭檔案程式碼
#ifndef GAUGEEDIT_H #define GAUGEEDIT_H /** * 可輸入儀表盤控制元件 作者:feiyangqingyun(QQ:517216493) 2019-09-11 * 1:可設定範圍值,支援負數值 * 2:可設定開始旋轉角度/結束旋轉角度 * 3:可設定是否啟用動畫效果以及動畫效果每次移動的步長 * 4:可設定外圓背景/內圓背景/進度顏色/空餘顏色/文字顏色 * 5:自適應窗體拉伸,文字自動縮放 * 6:支援tab及滑鼠按下切換焦點 * 7:支援直接輸入值立即應用 * 8:獲取焦點控制元件自動變大 * 9:支援鍵盤上下鍵步長為1修改值 * 10:支援上下翻頁鍵步長為10修改值 * 11:支援滑鼠滾輪步長為1修改值 */ #include <QWidget> class QLineEdit; #ifdef quc #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) #include <QtDesigner/QDesignerExportWidget> #else #include <QtUiPlugin/QDesignerExportWidget> #endif class QDESIGNER_WIDGET_EXPORT GaugeEdit : public QWidget #else class GaugeEdit : public QWidget #endif { Q_OBJECT Q_PROPERTY(double minValue READ getMinValue WRITE setMinValue) Q_PROPERTY(double maxValue READ getMaxValue WRITE setMaxValue) Q_PROPERTY(double value READ getValue WRITE setValue) Q_PROPERTY(QString unit READ getUnit WRITE setUnit) Q_PROPERTY(int startAngle READ getStartAngle WRITE setStartAngle) Q_PROPERTY(int endAngle READ getEndAngle WRITE setEndAngle) Q_PROPERTY(bool animation READ getAnimation WRITE setAnimation) Q_PROPERTY(double animationStep READ getAnimationStep WRITE setAnimationStep) Q_PROPERTY(QColor outerCircleColor READ getOuterCircleColor WRITE setOuterCircleColor) Q_PROPERTY(QColor innerCircleColor READ getInnerCircleColor WRITE setInnerCircleColor) Q_PROPERTY(QColor centerCircleColor READ getCenterCircleColor WRITE setCenterCircleColor) Q_PROPERTY(QColor usedColor READ getUsedColor WRITE setUsedColor) Q_PROPERTY(QColor freeColor READ getFreeColor WRITE setFreeColor) Q_PROPERTY(QColor textColor READ getTextColor WRITE setTextColor) public: explicit GaugeEdit(QWidget *parent = 0); ~GaugeEdit(); protected: bool eventFilter(QObject *watched, QEvent *event); void resizeEvent(QResizeEvent *); void paintEvent(QPaintEvent *); void drawOuterCircle(QPainter *painter); void drawInnerCircle(QPainter *painter); void drawProgress(QPainter *painter); void drawCenterCircle(QPainter *painter); void drawUnit(QPainter *painter); private slots: void initStyle(); void updateValue(); void textChanged(const QString &value); private: double minValue; //最小值 double maxValue; //最大值 double value; //目標值 QString unit; //單位 int startAngle; //開始旋轉角度 int endAngle; //結束旋轉角度 bool animation; //是否啟用動畫顯示 double animationStep; //動畫顯示時步長 QColor outerCircleColor; //外圓背景顏色 QColor innerCircleColor; //內圓背景顏色 QColor centerCircleColor; //中心圓顏色 QColor usedColor; //進度顏色 QColor freeColor; //空餘顏色 QColor textColor; //文字顏色 bool reverse; //是否往回走 double currentValue; //當前值 QTimer *timer; //定時器繪製動畫 int offset; //偏移值 QLineEdit *lineEdit; //編輯框 public: double getMinValue() const; double getMaxValue() const; double getValue() const; QString getUnit() const; int getStartAngle() const; int getEndAngle() const; bool getAnimation() const; double getAnimationStep() const; QColor getOuterCircleColor() const; QColor getInnerCircleColor() const; QColor getCenterCircleColor() const; QColor getUsedColor() const; QColor getFreeColor() const; QColor getTextColor() const; QSize sizeHint() const; QSize minimumSizeHint() const; public Q_SLOTS: //設定範圍值 void setRange(double minValue, double maxValue); void setRange(int minValue, int maxValue); //設定最大最小值 void setMinValue(double minValue); void setMaxValue(double maxValue); //設定目標值 void setValue(double value); void setValue(int value); //設定單位 void setUnit(const QString &unit); //設定開始旋轉角度 void setStartAngle(int startAngle); //設定結束旋轉角度 void setEndAngle(int endAngle); //設定是否啟用動畫顯示 void setAnimation(bool animation); //設定動畫顯示的步長 void setAnimationStep(double animationStep); //設定外圓背景顏色 void setOuterCircleColor(const QColor &outerCircleColor); //設定內圓背景顏色 void setInnerCircleColor(const QColor &innerCircleColor); //設定中心圓顏色 void setCenterCircleColor(const QColor ¢erCircleColor); //設定進度顏色 void setUsedColor(const QColor &usedColor); //設定空餘顏色 void setFreeColor(const QColor &freeColor); //設定文字顏色 void setTextColor(const QColor &textColor); Q_SIGNALS: void valueChanged(int value); }; #endif // GAUGEEDIT_H
五、核心程式碼
void GaugeEdit::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); //繪製外圓 drawOuterCircle(&painter); //繪製內圓 drawInnerCircle(&painter); //繪製當前進度 drawProgress(&painter); //繪製中心圓 drawCenterCircle(&painter); //繪製單位 drawUnit(&painter); } void GaugeEdit::drawOuterCircle(QPainter *painter) { int radius = 91 + offset; painter->save(); painter->setPen(Qt::NoPen); painter->setBrush(outerCircleColor); painter->drawEllipse(-radius, -radius, radius * 2, radius * 2); painter->restore(); } void GaugeEdit::drawInnerCircle(QPainter *painter) { int radius = 80 + offset; painter->save(); painter->setPen(Qt::NoPen); painter->setBrush(innerCircleColor); painter->drawEllipse(-radius, -radius, radius * 2, radius * 2); painter->restore(); } void GaugeEdit::drawProgress(QPainter *painter) { int radius = 75 + offset; painter->save(); painter->setPen(Qt::NoPen); QRectF rect(-radius, -radius, radius * 2, radius * 2); //計算總範圍角度,當前值範圍角度,剩餘值範圍角度 double angleAll = 360.0 - startAngle - endAngle; double angleCurrent = angleAll * ((currentValue - minValue) / (maxValue - minValue)); double angleOther = angleAll - angleCurrent; //繪製當前值餅圓 painter->setBrush(usedColor); painter->drawPie(rect, (270 - startAngle - angleCurrent) * 16, angleCurrent * 16); //繪製剩餘值餅圓 painter->setBrush(freeColor); painter->drawPie(rect, (270 - startAngle - angleCurrent - angleOther) * 16, angleOther * 16); painter->restore(); } void GaugeEdit::drawCenterCircle(QPainter *painter) { int radius = 60 + offset; painter->save(); painter->setPen(Qt::NoPen); painter->setBrush(centerCircleColor); painter->drawEllipse(-radius, -radius, radius * 2, radius * 2); painter->restore(); } void GaugeEdit::drawUnit(QPainter *painter) { int radius = 100; painter->save(); painter->setPen(textColor); QFont font; font.setPixelSize(30); painter->setFont(font); int offsetY = 110; QRectF unitRect(-radius, -radius + offsetY, radius * 2, radius * 2 - offsetY); painter->drawText(unitRect, Qt::AlignCenter, unit); painter->restore(); }
六、控制元件介紹
- 超過150個精美控制元件,涵蓋了各種儀表盤、進度條、進度球、指南針、曲線圖、標尺、溫度計、導航條、導航欄,flatui、高亮按鈕、滑動選擇器、農曆等。遠超qwt整合的控制元件數量。
- 每個類都可以獨立成一個單獨的控制元件,零耦合,每個控制元件一個頭檔案和一個實現檔案,不依賴其他檔案,方便單個控制元件以原始碼形式整合到專案中,較少程式碼量。qwt的控制元件類環環相扣,高度耦合,想要使用其中一個控制元件,必須包含所有的程式碼。
- 全部純Qt編寫,QWidget+QPainter繪製,支援Qt4.6到Qt5.12的任何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://pan.baidu.com/s/1A5Gd77kExm8Co5ckT51vvQ