Qt Writes Custom Control 65-Halo Calendar

Keywords: Mobile Qt Qt5 Linux SDK

I. Preface

Operating system update iteration speed is very fast, basically three or five years have a new version, WIN10 operating system is still a relatively successful system, it is said that now the market share is growing, XP share has been small, WIN7 share is gradually decreasing, in the latest WIN10 system, the lower right corner has a calendar control, or has its own lunar calendar, this localization is brutal. Okay, the mouse moves up and has a halo background effect. The experience is very pleasant, so I plan to use Qt to imitate one. There are two technical difficulties in this control. One is to arrange the weeks and dates automatically according to the current month. The other is to draw the halo background automatically. We need to use the image overlay mode set Composition Mode in painter. After setting the image overlay mode, we can overlap several drawings and combine them according to the set rules, such as drawing the halo background on the back. Later.

II. Functions of Realization

  • 1: Background color can be set
  • 2: Can set halo color
  • 3: Text color can be set
  • 4: Selected date background can be set
  • 5: Halo Follows Mouse Move

III. EFFECT CHARACTERISTICS

Header file code

#ifndef SHADOWCALENDAR_H
#define SHADOWCALENDAR_H

/**
 * Author of Halo Calendar Control: Yutian Ge (QQ:3246214072):feiyang Qingyun (QQ: 517216493) 2019-10-07
 * 1:Settable background color
 * 2:Settable halo color
 * 3:Text color can be set
 * 4:Selected date background can be set
 * 5:Halo Follows Mouse Move
 */

#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;             //background color
    QColor textColor;           //Text color
    QColor shadowColor;         //Halo Color
    QColor selectColor;         //Choose the color

    QDate selectDate;           //Today's date
    DateItem dateItem[6][7];    //Date array

public:
    QColor getBgColor()         const;
    QColor getTextColor()       const;
    QColor getShadowColor()     const;
    QColor getSelectColor()     const;

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

public Q_SLOTS:
    //Set background color + text color + halo color + select color
    void setBgColor(const QColor &bgColor);
    void setTextColor(const QColor &textColor);
    void setShadowColor(const QColor &shadowColor);
    void setSelectColor(const QColor &selectColor);
};

#endif // SHADOWCALENDAR_H


V. Core Code

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);

    //Drawing halo background
    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);
            }
        }

        //Drawing a circular halo background
        painter.fillRect(0, 0, sw, sh, QColor(200, 200, 200, 50));
    }

    //Draw Chinese numerals in the head, first set the image superposition mode as the source on it.
    painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
    painter.setPen(textColor);
    QStringList listHead;
    listHead << "one" << "two" << "three" << "four" << "five" << "six" << "day";
    for (int i = 0; i < 7; i++) {
        painter.drawText(i * iw, 0, iw, ih, Qt::AlignCenter, listHead.at(i));
    }

    //Drawing Date
    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 the date is selected, highlight the drawing background
                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 it overlaps with halo effect, the border is highlighted
                    if (rect.contains(point)) {
                        painter.setPen(QPen(selectColor.lighter(), 2));
                    }

                    //Draw rounded border
                    painter.drawRoundedRect(rect, 2, 2);

                    //Draw the background inside
                    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));
            }
        }
    }
}

Introduction of Control

  1. More than 160 exquisite controls, covering a variety of dashboards, progress bars, progress balls, compasses, curves, rulers, thermometers, navigation bars, navigation bars, flatui, highlighted buttons, sliding selectors, the lunar calendar and so on. Far more controls than qwt integrates.
  2. Each class can be separated into a separate control, zero-coupling, each control has a header file and an implementation file, independent of other files, to facilitate the integration of a single control in the form of source code into the project, less code. The control classes of qwt are interlinked and highly coupled. If you want to use one of the controls, you must include all the code.
  3. All pure Qt writing, QWidget+QPainter drawing, support any Qt version from Qt4.6 to Qt5.13, support mingw, msvc, gcc and other compilers, support any operating system such as windows+linux+mac + embedded linux, no scrambling, can be directly integrated into Qt Creator, as with its own controls, most of the effects can be set as few attributes, very convenient.
  4. Each control has a corresponding separate DEMO containing the source code of the control, which is convenient for reference. It also provides an integrated DEMO for all controls.
  5. The source code of each control has detailed Chinese annotations, which are compiled in accordance with the unified design specifications. It is convenient to learn how to compile custom controls.
  6. Each control's default color matching and demo's corresponding color matching are very beautiful.
  7. More than 130 visible controls and 6 invisible controls.
  8. Some controls provide a variety of style choices, a variety of indicator style choices.
  9. All controls adapt to form stretching changes.
  10. Integrate custom control property designer, support drag design, WYSIWYG, support import and export xml format.
  11. With activex control demo, all controls can run directly in ie browser.
  12. Integrate fontawesome graphic fonts + hundreds of graphic fonts collected by Alibaba iconfont to enjoy the fun of graphic fonts.
  13. All controls eventually generate a dynamic library file (dll or so, etc.) that can be directly integrated into the qtcreator to drag the design to use.
  14. At present, there is a version of qml, pyqt version will be considered later, if the user demand is large.
  15. Custom Control Plug-in Open Dynamic Library (permanently free), without any backdoor and restrictions, please feel free to use.
  16. At present, 32 versions of dll have been provided, of which qt_5_7_0_mingw530_32 will always guarantee the latest integrity.
  17. Increase control and improve control from time to time, update SDK from time to time. Welcome to make suggestions. Thank you!
  18. Qt introductory books recommend Hoyafei's Quick Start to Qt Creator, Qt5 Programming Introduction, and Qt advanced books recommend the official C++ GUI Qt4 Programming.
  19. I strongly recommend programmers'self-cultivation and planning series "Talking about Programmers", "Programmers' Growth Course" and "Solution Programmers". They benefit a lot and benefit a lifetime!
  20. SDK address: https://gitee.com/feiyangqingyun/QUCSDK https://github.com/feiyangqingyun/qucsdk

Posted by stanleycwb on Wed, 09 Oct 2019 21:23:17 -0700