天天看點

Qt開源作品30-農曆控件

一、前言

農曆控件在國産linux中必備的控件之一,畢竟要适應國人的習慣,你看win10系統的月曆,現在點開來直接就有農曆在上面,非常友善人性化,是以在很多用Qt做的項目中,也有農曆控件的應用場景,而Qt自帶的月曆控件比較簡單,仔細看過源碼的人也隻知道,其實就是一堆微調框,下拉框,表格組成的,于是打算借用此方法造一個農曆控件,本控件的算法是倪大俠提供的,個人測試下來還是沒有問題的,造這個農曆控件最大的難點是如何根據日期計算農曆時間,再加上一些農曆的節氣之類的,這個網上估計也有很多的算法參考。

主要功能:

  1. 可設定邊框顔色/周末顔色/角标顔色/農曆節日顔色
  2. 可設定目前月文字顔色/其他月文字顔色/選中日期文字顔色/懸停日期文字顔色
  3. 可設定目前月農曆文字顔色/其他月農曆文字顔色/選中日期農曆文字顔色/懸停日期農曆文字顔色
  4. 可設定目前月背景顔色/其他月背景顔色/選中日期背景顔色/懸停日期背景顔色
  5. 可設定三種選中背景模式,矩形背景+圓形背景+圖檔背景
  6. 可直接切換到上一年/下一年/上一月/下一月/轉到今天
  7. 可設定是否顯示農曆資訊,不顯示則當做正常的月曆使用
  8. 支援1900年-2099年範圍
  9. 很友善改成多選日期

二、代碼思路

void LunarCalendarItem::paintEvent(QPaintEvent *)
{
    //繪制準備工作,啟用反鋸齒
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);

    //繪制背景和邊框
    drawBg(&painter);

    //優先繪制選中狀态,其次繪制懸停狀态
    if (select) {
        drawBgCurrent(&painter, selectBgColor);
    } else if (hover) {
        drawBgCurrent(&painter, hoverBgColor);
    }

    //繪制日期
    drawDay(&painter);

    //繪制農曆資訊
    drawLunar(&painter);
}

void LunarCalendarItem::drawBg(QPainter *painter)
{
    painter->save();

    //根據目前類型選擇對應的顔色
    QColor bgColor = currentBgColor;
    if (dayType == DayType_MonthPre || dayType == DayType_MonthNext) {
        bgColor = otherBgColor;
    }

    painter->setPen(borderColor);
    painter->setBrush(bgColor);
    painter->drawRect(rect());

    painter->restore();
}

void LunarCalendarItem::drawBgCurrent(QPainter *painter, const QColor &color)
{
    int width = this->width();
    int height = this->height();
    int side = qMin(width, height);

    painter->save();

    painter->setPen(Qt::NoPen);
    painter->setBrush(color);

    //根據設定繪制背景樣式
    if (selectType == SelectType_Rect) {
        painter->drawRect(rect());
    } else if (selectType == SelectType_Circle) {
        int radius = side / 2 - 3;
        painter->drawEllipse(QPointF(width / 2, height / 2), radius, radius);
    } else if (selectType == SelectType_Triangle) {
        int radius = side / 3;
        QPolygon pts;
        pts.setPoints(3, 1, 1, radius, 1, 1, radius);
        painter->drawRect(rect());
        painter->setBrush(superColor);
        painter->drawConvexPolygon(pts);
    } else if (selectType == SelectType_Image) {
        //等比例縮放居中繪制
        QImage img(bgImage);
        if (!img.isNull()) {
            img = img.scaled(this->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
            int x = (width - img.width()) / 2;
            int y = (height - img.height()) / 2;
            painter->drawImage(x, y, img);
        }
    }

    painter->restore();
}

void LunarCalendarItem::drawDay(QPainter *painter)
{
    int width = this->width();
    int height = this->height();
    int side = qMin(width, height);

    painter->save();

    //根據目前類型選擇對應的顔色
    QColor color = currentTextColor;
    if (dayType == DayType_MonthPre || dayType == DayType_MonthNext) {
        color = otherTextColor;
    } else if (dayType == DayType_WeekEnd) {
        color = weekColor;
    }

    if (select) {
        color = selectTextColor;
    } else if (hover) {
        color = hoverTextColor;
    }

    painter->setPen(color);

    if (showLunar) {
        QFont font;
        font.setPixelSize(side / 2.7);
        painter->setFont(font);

        QRect dayRect = QRect(0, 0, width, height / 1.7);
        painter->drawText(dayRect, Qt::AlignHCenter | Qt::AlignBottom, QString::number(date.day()));
    } else {
        QFont font;
        font.setPixelSize(side / 2);
        painter->setFont(font);

        QRect dayRect = QRect(0, 0, width, height);
        painter->drawText(dayRect, Qt::AlignCenter, QString::number(date.day()));
    }

    painter->restore();
}

void LunarCalendarItem::drawLunar(QPainter *painter)
{
    if (!showLunar) {
        return;
    }

    int width = this->width();
    int height = this->height();
    int side = qMin(width, height);

    painter->save();

    //判斷目前農曆文字是否節日,是節日且是當月則用農曆節日顔色顯示
    bool exist = (!listDayName.contains(lunar) && dayType != DayType_MonthPre && dayType != DayType_MonthNext);

    //根據目前類型選擇對應的顔色
    QColor color = currentLunarColor;
    if (dayType == DayType_MonthPre || dayType == DayType_MonthNext) {
        color = otherLunarColor;
    }

    if (select) {
        color = selectTextColor;
    } else if (hover) {
        color = hoverTextColor;
    } else if (exist) {
        color = lunarColor;
    }

    painter->setPen(color);

    QFont font;
    font.setPixelSize(side / 5);
    painter->setFont(font);    

    QRect lunarRect(0, height / 2, width, height / 2);
    painter->drawText(lunarRect, Qt::AlignCenter, lunar);

    painter->restore();
}           

三、效果圖

Qt開源作品30-農曆控件

四、開源首頁

以上作品完整源碼下載下傳都在開源首頁,會持續不斷更新作品數量和品質,歡迎各位關注。

  1. 國内站點: https://gitee.com/feiyangqingyun/QWidgetDemo
  2. 國際站點: https://github.com/feiyangqingyun/QWidgetDemo
  3. 個人首頁: https://blog.csdn.net/feiyangqingyun
  4. 知乎首頁: https://www.zhihu.com/people/feiyangqingyun/

繼續閱讀