qt中split函数怎么用_用Qt实现类似Win10系统中的日历光晕效果(一种思路)

本文介绍了如何在Qt项目中实现Win10日历的光晕效果,通过QPainter的图像组合模式绘制光晕背景,并提供了相关代码实现。文章详细讲解了绘制过程,包括计算日期、设置颜色以及绘制光晕和日期,为开发者提供了一种实现思路。
摘要由CSDN通过智能技术生成

32f710643e0d0c6b19441ccb1845551c.png

总第48篇

本文主要总结一下在Qt项目中,如何绘制类似Win10系统中的日历光晕效果,并给出绘制代码,方便以后在项目中学习与参考。

Win10系统中,光晕日历的效果如下图所示。

d9ce9eaa0c7ed0c004eb44d91b8a2774.gif

Qt来绘制这个控件有两个难点,一个是要自己计算当前月份的日期并自动排列成星期,二是绘制这种光晕背景。其中绘制光晕效果要用到QPainter的图像组合模式,通过官方文档,可以看到,QPainter有多种图像组合模式,可通过接口setCompositionMode()接口来设置。下图展示了几种基本的图像组合模式的效果。

bdc66d06f568ef5423205237754ea9e5.png

不多说了,上一下核心代码。下面是头文件的定义,提供了设置背景颜色、光晕颜色、文字颜色、日期背景等接口。

#ifndef SHADOWCALENDAR_H
#define SHADOWCALENDAR_H

#include <QWidget>
#include <QDate>

class ShadowCalendar : public QWidget
{
    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;

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

其程序运行的结果如下图所示:

c61a01e911bf83654b4c37086d32cddf.gif

上面这种绘制方法只是提供了一种思路,为大家提供参考,更好的实现方法,可以在项目开发过程进行精进探索。

本文到此结束!

如果对你有帮助,请随手 点赞点喜欢!关注本专栏,更多干货与你分享。

=======================================================

欢迎【关注、私信 @武三郎。我们一起交流一起进步。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值