這個控件是近期定製的控件,仍是比較實用的控件之一,用戶主要是提了三點需求,一點是切換焦點的時候控件放大突出顯示,一點是可直接輸入或者編輯值,還有一點是支持上下鍵及翻頁鍵和鼠標滾輪來動態修改值,相似於qspinbox控件。要可以支持直接輸入首先想到的就是qlineedit控件,在原有的儀表盤控件上中間部分,放置一個qlineedit控件用來輸入值,採用正則表達式來限制只能輸入數字,爲了使得qlinedit和自定義繪製的儀表盤徹底融爲一體,必須設置qlineedit的樣式爲背景透明,至於輸入框的位置,有個小技巧就是直接將輸入框設置爲控件的大小,這樣輸入的焦點永遠在控件的中間,徹底混合,絲毫看不出是一個輸入框控件插在那裏,至於上下鍵及翻頁鍵和鼠標滾輪,直接安裝事件過濾器便可識別到,進行對應的處理便可。linux
#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(); }