操做系統的更新迭代速度很是快,基本上三五年就有個新版本出來,WIN10操做系統仍是一個比較成功的系統,聽說如今市場份額愈來愈大,XP的份額已經很小,WIN7的份額也在逐步減小,在最新的WIN10系統中,右下角有個日曆控件,仍是自帶農曆的,這個本地化作的蠻好的,鼠標移上去還有光暈背景效果,體驗很是賞心悅目,因而打算用Qt也高仿一個。
本控件的技術難點有兩個,一個是根據當前月份自動排列星期和日期,這個須要自動計算的,難點二是繪製光暈背景,須要用到painter中的圖像疊加模式setCompositionMode,設置好圖像疊加模式之後,能夠將多個繪製重疊,按照設定的規則組合,好比將光暈背景繪製在背後。linux
#ifndef SHADOWCALENDAR_H #define SHADOWCALENDAR_H /** * 光暈日曆控件 做者:雨田哥(QQ:3246214072) 整理:feiyangqingyun(QQ:517216493) 2019-10-07 * 1:可設置背景顏色 * 2:可設置光暈顏色 * 3:可設置文字顏色 * 4:可設置選中日期背景 * 5:光暈跟隨鼠標移動 */ #include <QWidget> #include <QDate> #ifdef quc #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) #include <QtDesigner/QDesignerExportWidget> #else #include <QtUiPlugin/QDesignerExportWidget> #endif class QDESIGNER_WIDGET_EXPORT ShadowCalendar : public QWidget #else class ShadowCalendar : public QWidget #endif { Q_OBJECT Q_PROPERTY(QColor bgColor READ getBgColor WRITE setBgColor) Q_PROPERTY(QColor textColor READ getTextColor WRITE setTextColor) Q_PROPERTY(QColor shadowColor READ getShadowColor WRITE setShadowColor) Q_PROPERTY(QColor selectColor READ getSelectColor WRITE setSelectColor) public: struct DateItem { int year; int month; int day; DateItem() { year = -1; month = -1; day = -1; } }; explicit ShadowCalendar(QWidget *parent = 0); ~ShadowCalendar(); public: void updateCalendar(const QDate &selectDate); protected: void leaveEvent(QEvent *); void mouseMoveEvent(QMouseEvent *); void paintEvent(QPaintEvent *); private: QColor bgColor; //背景顏色 QColor textColor; //文字顏色 QColor shadowColor; //光暈顏色 QColor selectColor; //選中顏色 QDate selectDate; //今天日期 DateItem dateItem[6][7]; //日期數組 public: QColor getBgColor() const; QColor getTextColor() const; QColor getShadowColor() const; QColor getSelectColor() const; QSize sizeHint() const; QSize minimumSizeHint() const; public Q_SLOTS: //設置背景顏色+文字顏色+光暈顏色+選中顏色 void setBgColor(const QColor &bgColor); void setTextColor(const QColor &textColor); void setShadowColor(const QColor &shadowColor); void setSelectColor(const QColor &selectColor); }; #endif // SHADOWCALENDAR_H
void ShadowCalendar::paintEvent(QPaintEvent *) { QPainter painter(this); painter.setRenderHints(QPainter::Antialiasing); int sw = 336; int sh = 336; qreal scaleX = this->width() * 1.0 / sw; qreal scaleY = this->height() * 1.0 / sh; painter.scale(scaleX, scaleY); painter.setPen(Qt::NoPen); painter.fillRect(0, 0, sw, sh, bgColor); qreal iw = sw / 7.0; qreal ih = sh / 7.0; //mask QPointF globalpoint = this->mapFromGlobal(QCursor::pos()); const QPointF &point = QPointF(globalpoint.x() / scaleX, globalpoint.y() / scaleY); //繪製光暈背景 if (this->underMouse()) { int effectradius = 58; painter.setCompositionMode(QPainter::CompositionMode_DestinationIn); QRadialGradient radialGrad(point, effectradius); radialGrad.setColorAt(0, QColor(0, 0, 0, 120)); radialGrad.setColorAt(1, QColor(0, 0, 0, 255)); painter.setBrush(radialGrad); painter.drawEllipse(point, effectradius, effectradius); painter.setCompositionMode(QPainter::CompositionMode_DestinationOver); painter.setBrush(Qt::NoBrush); for (int row = 0; row < 6; row++) { for (int column = 0; column < 7; column++) { QRectF rect = QRectF(column * iw, (row + 1) * ih, iw, ih).adjusted(3, 3, -3, -3); if (rect.contains(point)) { painter.save(); painter.setCompositionMode(QPainter::CompositionMode_SourceOver); painter.setPen(QPen(QColor(220, 220, 220, 160), 2)); painter.drawRoundedRect(rect, 2, 2); painter.restore(); continue; } else { painter.setPen(QPen(shadowColor, 2)); } painter.drawRoundedRect(rect, 2, 2); } } //繪製圓形的光暈底層背景 painter.fillRect(0, 0, sw, sh, QColor(200, 200, 200, 50)); } //繪製頭部中文數字,先設置圖像疊加模式爲源在上面 painter.setCompositionMode(QPainter::CompositionMode_SourceOver); painter.setPen(textColor); QStringList listHead; listHead << "一" << "二" << "三" << "四" << "五" << "六" << "日"; for (int i = 0; i < 7; i++) { painter.drawText(i * iw, 0, iw, ih, Qt::AlignCenter, listHead.at(i)); } //繪製日期 for (int row = 0; row < 6; row++) { for (int column = 0; column < 7; column++) { if (dateItem[row][column].day > 0) { QRectF rect = QRectF(column * iw, (row + 1) * ih, iw, ih).adjusted(3, 3, -3, -3); //若是是選中的日期則突出繪製背景 if (QDate::currentDate() == QDate(dateItem[row][column].year, dateItem[row][column].month, dateItem[row][column].day)) { painter.setPen(QPen(selectColor, 2)); painter.setBrush(Qt::NoBrush); //若是和光暈效果重疊則邊框高亮 if (rect.contains(point)) { painter.setPen(QPen(selectColor.lighter(), 2)); } //繪製圓角邊框 painter.drawRoundedRect(rect, 2, 2); //繪製裏邊背景 painter.setPen(Qt::NoPen); painter.setBrush(selectColor); painter.drawRoundedRect(rect.adjusted(4, 4, -4, -4), 2, 2); } painter.setPen(textColor); painter.drawText(rect, Qt::AlignCenter, QString::number(dateItem[row][column].day)); } } } }