码迷,mamicode.com
首页 > 其他好文 > 详细

Qt 制作带农历的日历

时间:2016-05-05 11:08:28      阅读:328      评论:0      收藏:0      [点我收藏+]

标签:

网上农历算法很多,大部分都是比较准的,但是在Qt里面很少有朋友整理和共享出来,在此,花一点时间整理下资料和想法,顺便或许也能帮助一些新手朋友!

首先讲讲设计思路吧,没有采用系统自带的QCalendarWidget,而是通过42个QLabel拼凑出来的一个界面,之所以采用这种拼凑的方法是方便管理样式,话不多说了上图和代码吧:

技术分享


先来界面布局代码吧:


#ifndef CALENDARWIDGET_H
#define CALENDARWIDGET_H

#include <QWidget>
#include <QLabel>

QT_BEGIN_NAMESPACE
class QPushButton;
class QComboBox;
class QGroupBox;
class QLineEdit;
class QDate;
class QGridLayout;
class QHBoxLayout;
class QVBoxLayout;

class Event;
class DataBase;
QT_END_NAMESPACE

typedef enum {
    Sunday,
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Week
} E_WEEK;

typedef enum {
    PREV_MONTH_DAY,     // 上月剩余天数
    NEXT_MONTH_DAY,     // 下个月的天数
    CURR_MONTH_DAY,     // 当月天数
    WEEKEND_DAY,        // 周末
    CURRENT_DAY,        // 当天
} E_DAY;

///////////////////////////////////////////////
/// \brief The DayLabel class
/// 自定义的日子显示控件
///////////////////////////////////////////////
class DayLabel : public QLabel {
    Q_OBJECT

public:
    explicit DayLabel(QWidget *parent = 0);

    bool bSelect;
    bool getBSelect() const;
    void setSelected(bool value);
    void setColor(const int &type);
    void showDay(int nDay, QString strLunar);

    int m_nDay;
    void setPlan(QStringList plan);
signals:
    void signalClicked(int ntype, int day);
    void signalPlan(const QString &content);
private:
    QLabel *labelIcon;
    QStringList m_strListPlan;
protected:
    void enterEvent(QEvent *e);
    void leaveEvent(QEvent *e);
    void mousePressEvent(QMouseEvent *e);
    void mouseDoubleClickEvent(QMouseEvent *e);
};

/////////////////////////////////////////////////
/// \brief The CalendarWidget class
/// 日历界面
////////////////////////////////////////////////
class CalendarWidget : public QWidget
{
    Q_OBJECT

public:
    explicit CalendarWidget(QWidget *parent = 0);
    ~CalendarWidget();

    int year() const;
    void setYear(int year);

    int month() const;
    void setMonth(int month);

    int day() const;
    void setDay(int day);

    void jumpTodate(int year, int month, int day);
signals:
    void signalDayClicked(int nday);
    void signalDayChanged();
    void signalPlan(const QString &content);
private:
    QVBoxLayout *verLayoutCalendar;

    QWidget *widgetTitle;
    QLabel *labelTitle;
    QPushButton *btnPrevMonth;
    QPushButton *btnNextMonth;
    QHBoxLayout *horLayoutTitle;

    QWidget *widgetWeek;
    QLabel *labelWeek[Week];
    QHBoxLayout *horLayoutWeek;

    QWidget *widgetBody;
    DayLabel *labelDay[42];
    QGridLayout *gridLayoutBody;

    QWidget *widgetRight;

    QLabel *labelShowToday;
    QLabel *labelShowWeek;
    QLabel *labelShowDay;
    QLabel *labelShowNYear;
    QLabel *labelShowLunarDate;
    QLabel *labelSpacer;
    QLabel *labelScheduleTitle;
    QLabel *labelSchedule;

    QVBoxLayout *verlayoutWidgetRight;

    QHBoxLayout *horLayoutGlobal;

private:
    int m_nYear;
    int m_nMonth;
    int m_nDay;
private:
    void initWidget();<pre name="code" class="cpp">#include "calendarwidget.h"
#include "date.h"
#include "database.h"

#include <QInputDialog>
#include <QPainter>
#include <QStyleOption>
#include <QDateTime>
#include <QPushButton>
#include <QLineEdit>
#include <QGroupBox>
#include <QLabel>
#include <QDate>
#include <QGridLayout>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QSpacerItem>
#include <QDebug>
#include <QFont>

static const QString s_strWeek[] = {
    QObject::tr("周日"), QObject::tr("周一"), QObject::tr("周二"),
    QObject::tr("周三"), QObject::tr("周四"), QObject::tr("周五"),
    QObject::tr("周六"),
};

CalendarWidget::CalendarWidget(QWidget *parent)
    : QWidget(parent), m_nMonth(1)
{
    // 获取当前年月日
    m_nYear  = QDate::currentDate().year();
    m_nMonth = QDate::currentDate().month();
    m_nDay = QDate::currentDate().day();

    initWidget();
    initDate();
}

CalendarWidget::~CalendarWidget()
{

}

int CalendarWidget::year() const
{
    return m_nYear;
}

void CalendarWidget::setYear(int nYear)
{
    m_nYear = nYear;
}

int CalendarWidget::month() const
{
    return m_nMonth;
}

void CalendarWidget::setMonth(int nMonth)
{
    m_nMonth = nMonth;
}

int CalendarWidget::day() const
{
    return m_nDay;
}

void CalendarWidget::setDay(int nDay)
{
    m_nDay = nDay;
}

void CalendarWidget::jumpTodate(int year, int month, int day)
{
    setYear(year);
    setMonth(month);
    setDay(day);

    initDate();
}

/**
 * @brief CalendarWidget::initWidget 初始化界面
 */
void CalendarWidget::initWidget()
{
#ifdef Q_OS_ANDROID
    this->setMinimumSize(1400, 800);
#else
    this->setMinimumSize(427, 350);
    this->setObjectName("widgetCalendar");
#endif

    verLayoutCalendar = new QVBoxLayout(this);
    verLayoutCalendar->setContentsMargins(2, 2, 2, 2);
    verLayoutCalendar->setSpacing(0);

    //! [2]
    widgetTitle = new QWidget(this);
    widgetTitle->setObjectName("widgetTitle");

#ifdef Q_OS_ANDROID
    widgetTitle->setFixedHeight(80);
#else
    widgetTitle->setMinimumHeight(20);
#endif

    btnPrevMonth = new QPushButton(widgetTitle);
    btnPrevMonth->setText(tr("上月"));

    labelTitle = new QLabel(widgetTitle);
    labelTitle->setAlignment(Qt::AlignCenter);
    labelTitle->setObjectName("labelTitle");
    labelTitle->setText(tr("2016 年 04 月"));

    btnNextMonth = new QPushButton(widgetTitle);
    btnNextMonth->setText(tr("下月"));

    horLayoutTitle = new QHBoxLayout(widgetTitle);
    horLayoutTitle->addWidget(btnPrevMonth);
    horLayoutTitle->addWidget(labelTitle, 1);
    horLayoutTitle->addWidget(btnNextMonth);

    verLayoutCalendar->addWidget(widgetTitle);

    connect(btnPrevMonth, SIGNAL(clicked(bool)), this, SLOT(sltShowPrevMonth()));
    connect(btnNextMonth, SIGNAL(clicked(bool)), this, SLOT(sltShowNextMonth()));
    //! [2]

    //! [3]
    widgetWeek = new QWidget(this);
    widgetWeek->setObjectName("widgetWeek");

    horLayoutWeek = new QHBoxLayout(widgetWeek);
    horLayoutWeek->setContentsMargins(0, 0, 0, 0);
    horLayoutWeek->setSpacing(0);

    for (int i = 0; i < Week; i++) {
        labelWeek[i] = new QLabel(widgetWeek);
        labelWeek[i]->setText(s_strWeek[i]);
        labelWeek[i]->setObjectName("labelWeek");
        labelWeek[i]->setMinimumHeight(30);
        labelWeek[i]->setAlignment(Qt::AlignCenter);
        if ((0 == (i % 7)) || (6 == (i% 7))) {
            labelWeek[i]->setProperty("weekend", true);
        }
        horLayoutWeek->addWidget(labelWeek[i]);
    }

    verLayoutCalendar->addWidget(widgetWeek);
    //! [3]

    //! [4]
    widgetBody = new QWidget(this);
    verLayoutCalendar->addWidget(widgetBody, 1);

    gridLayoutBody = new QGridLayout(widgetBody);
    gridLayoutBody->setHorizontalSpacing(0);
    gridLayoutBody->setVerticalSpacing(0);
    gridLayoutBody->setContentsMargins(0, 0, 0, 0);

    for (int i = 0; i < 42; i++) {
        labelDay[i] = new DayLabel(widgetBody);
        labelDay[i]->setObjectName("labelDay");
        labelDay[i]->setAlignment(Qt::AlignCenter);
        labelDay[i]->setText(QString::number(i));
        if ((0 == (i % 7)) || (6 == (i% 7))) {
            labelDay[i]->setProperty("weekend", true);
        }
        gridLayoutBody->addWidget(labelDay[i], i / 7, i % 7);
        connect(labelDay[i], SIGNAL(signalClicked(int,int)), this, SLOT(sltDayClicked(int,int)));
        connect(labelDay[i], SIGNAL(signalPlan(QString)), this, SIGNAL(signalPlan(QString)));
    }

    labelDay[10]->setSelected(true);
    //! [4]
}

/**
 * @brief CalendarWidget::initDate 初始化日期
 */
void CalendarWidget::initDate()
{
    // 首先判断当前月的第一天是星期几
    int nWeek  = Date::getFirstDayOfWeek(m_nYear, m_nMonth);
    int nMonthDays = Date::getMonthDays(m_nYear, m_nMonth);
    // 上月天数
    int nPreMonDays = Date::getMonthDays(1 == m_nMonth ? m_nYear - 1 : m_nYear, 1 == m_nMonth ? 12 : m_nMonth - 1);

    // 显示当前年月
    labelTitle->setText(tr("%1 年 %2 月")
                        .arg(m_nYear, 2, 10, QChar('0'))
                        .arg(m_nMonth, 2, 10, QChar('0')));

    // 显示上月剩余天数
    if (0 == nWeek) {
        // 显示上月天数
        for (int i = 0; i < 7; i++) {
            labelDay[i]->showDay((nPreMonDays - 7 + i + 1), "");
            labelDay[i]->setColor(PREV_MONTH_DAY);
        }
        // 显示下月天数
        for (int i = 0; i < (42 - nMonthDays - 7); i++) {
            labelDay[nMonthDays + 7 + i]->showDay((i + 1), "");
            labelDay[nMonthDays + 7 + i]->setColor(NEXT_MONTH_DAY);
        }
    }
    else {
        for (int i = 0; i < nWeek; i++) {
            labelDay[i]->showDay((nPreMonDays - nWeek + i + 1), "");
            labelDay[i]->setColor(PREV_MONTH_DAY);
        }

        // 显示下月天数
        for (int i = (nWeek + nMonthDays); i < 42; i++) {
            labelDay[i]->showDay((i - (nWeek + nMonthDays) + 1), "");
            labelDay[i]->setColor(NEXT_MONTH_DAY);
        }
    }

    // 显示当前月
    int nProperty = 1;
    QStringList strPlan;
    int index = 0;
    for (int i = nWeek; i < (nMonthDays + nWeek); i++) {
        index = 0 == nWeek ? (i + 7) : i;
        labelDay[index]->showDay(i - nWeek + 1, Date::getLunarDate(m_nYear, m_nMonth, i - nWeek + 1));
        nProperty = ((0 == (i % 7)) || (6 == (i% 7))) ? WEEKEND_DAY : CURR_MONTH_DAY;
        labelDay[index]->setColor(nProperty);
        // 显示计划
        strPlan = DataBase::selectDb(
                    QString("%1-%2-%3")
                    .arg(m_nYear, 4, 10,  QChar('0'))
                    .arg(m_nMonth, 2, 10, QChar('0'))
                    .arg(i - nWeek + 1, 2, 10,   QChar('0')));

        // 显示计划
        labelDay[index]->setPlan(strPlan);
    }

    // 显示当前天数
    labelDay[m_nDay + nWeek - 1]->setColor(CURRENT_DAY);
    // 发送更新信号
    Q_EMIT signalDayChanged();
}

/**
 * @brief CalendarWidget::sltDayClicked 点击响应
 * @param type  类型 0 表示上月 1表示下月
 * @param day  当前点击的天数
 */
void CalendarWidget::sltDayClicked(int type, int day)
{
    // 上月
    if (PREV_MONTH_DAY == type) {
        sltShowPrevMonth();
    }
    // 下月
    else if (NEXT_MONTH_DAY == type) {
        sltShowNextMonth();
    }
    // 当天/周末/当月天数都显示在右边,并转换成农历
    else if ((CURR_MONTH_DAY == type)
             || (WEEKEND_DAY == type)
             || (CURRENT_DAY == type)) {
        // 选中当天
        Q_EMIT signalDayClicked(day);
    }
}

/**
 * @brief CalendarWidget::sltShowPrevMonth 显示上月日期
 */
void CalendarWidget::sltShowPrevMonth()
{
    m_nMonth--;
    if (m_nMonth < 1) {
        m_nMonth = 12;
        m_nYear--;
    }

    initDate();
}

/**
 * @brief CalendarWidget::sltShowNextMonth 显示下月日期
 */
void CalendarWidget::sltShowNextMonth()
{
    m_nMonth++;
    if (m_nMonth > 12) {
        m_nMonth = 1;
        m_nYear++;
    }
    initDate();
}

//////////////////////////////////////
/// \brief DayLabel::DayLabel
/// \param parent
////////////////////////////////

#include <QMouseEvent>
#include <QEvent>
#include <QPixmap>
#include "event.h"

DayLabel::DayLabel(QWidget *parent):
    QLabel(parent)
{
    bSelect = false;
    m_nDay = 0;
    m_strListPlan.clear();

    labelIcon = new QLabel(this);
    labelIcon->setFixedSize(QSize(12, 12));
    labelIcon->setPixmap(QPixmap(":/images/eventindicator.png"));
    labelIcon->move(0, 0);
    labelIcon->setVisible(false);
}

bool DayLabel::getBSelect() const
{
    return bSelect;
}

void DayLabel::setSelected(bool value)
{
    bSelect = value;
    this->setStyleSheet(QString("background: #ffffff; border: 1px solid red; border-radius: 2px"));
}

void DayLabel::setColor(const int &type)
{
    // 设置控件属性类型
    this->setProperty("type", type);
    this->setSelected(CURRENT_DAY == type);

    // 其他月
    if ((PREV_MONTH_DAY == type) || (NEXT_MONTH_DAY == type)) {
        this->setStyleSheet("background: #ffffff; border-top: 1px solid #c3c3c3; border-left: 1px solid #c3c3c3; color: #999999;");
        labelIcon->setVisible(false);
    }
    // 当前月
    else if (CURR_MONTH_DAY == type) {
        this->setStyleSheet("background: #ffffff; border-top: 1px solid #c3c3c3; border-left: 1px solid #c3c3c3; color: #000000;");
    }
    // 周末
    else if (WEEKEND_DAY == type) {
        labelIcon->setVisible(false);
        this->setStyleSheet("background: #ffffff; border-top: 1px solid #c3c3c3; border-left: 1px solid #c3c3c3; color: #ff0000;");
    }
}

/**
 * @brief DayLabel::showDay
 * @param nDay
 * @param strLunar
 * @param type
 */
void DayLabel::showDay(int nDay, QString strLunar)
{
    QString strText = QString::number(nDay);
    this->m_nDay = nDay;

    if ("" != strLunar) {
        strText.append("\n");
        strText.append(strLunar);
    }

    this->setText(strText);
}

/**
 * @brief DayLabel::setPlan 设置计划和日程
 * @param plan
 */
void DayLabel::setPlan(QStringList plan)
{
    if (!plan.isEmpty()) {
        m_strListPlan = plan;
        this->setToolTip(m_strListPlan.at(1));
    }
    else {
        labelIcon->setVisible(false);
        m_strListPlan.clear();
    }
}

void DayLabel::enterEvent(QEvent *e)
{
    int nProperty = this->property("type").toInt();
    if (PREV_MONTH_DAY == nProperty || NEXT_MONTH_DAY == nProperty) return;

    this->setStyleSheet("background: #c8b9a6; border-top: 1px solid #c3c3c3; border-left: 1px solid #c3c3c3;");
    QLabel::enterEvent(e);
}

void DayLabel::leaveEvent(QEvent *e)
{
    int nProperty = this->property("type").toInt();
    if (PREV_MONTH_DAY == nProperty || NEXT_MONTH_DAY == nProperty) return;

    if (bSelect) {
        this->setStyleSheet("background: #ffffff; border: 1px solid red;");
    }
    else {
        this->setStyleSheet("background: #ffffff; border-top: 1px solid #c3c3c3; border-left: 1px solid #c3c3c3;");
    }
    QLabel::leaveEvent(e);
}

void DayLabel::mousePressEvent(QMouseEvent *e)
{
//    qDebug() << this->text() << this->property("type").toInt();
    Q_EMIT signalClicked(this->property("type").toInt(), m_nDay);
    if (!m_strListPlan.isEmpty()) {
        Q_EMIT signalPlan(m_strListPlan.at(1));
    }
    else {
         Q_EMIT signalPlan(tr("没有日程安排"));
    }
    QLabel::mousePressEvent(e);
}

void DayLabel::mouseDoubleClickEvent(QMouseEvent *e)
{
    //    qDebug() << "double";
    int nProperty = this->property("type").toInt();
    if (PREV_MONTH_DAY == nProperty || NEXT_MONTH_DAY == nProperty) return;

    bool ok;
    QString strText = "";
    if (!m_strListPlan.isEmpty()) {
        strText = m_strListPlan.at(1);
    }

    strText = QInputDialog::getText(this, tr("修改日程"),
                                         tr("您的出行计划"), QLineEdit::Normal,
                                         strText, &ok);
    if (ok && !strText.isEmpty())
        qDebug() << strText;
    QLabel::mouseDoubleClickEvent(e);
}

//////////////////////////////////////////
/// \brief Window::Window
/// \param parent
/////////////////////////////////////////

#include <QMessageBox>
#include "database.h"

Window::Window(QWidget *parent) :
    QWidget(parent)
{
    // 初始化数据库
    DataBase::connectdb();

    initWidget();
    initStyle();
    initDatabase();
}

Window::~Window()
{
}

void Window::initWidget()
{
    //! [1]
    calendar = new CalendarWidget(this);
    //! [1]

    //! [2]
    widgetRight     = new QWidget(this);
    widgetRight->setObjectName("widgetRight");
//    widgetRight->setMinimumSize(160, 350);

    labelShowToday       = new QLabel(widgetRight);
    labelShowWeek        = new QLabel(widgetRight);
    labelShowDay         = new QLabel(widgetRight);
    labelShowNYear       = new QLabel(widgetRight);
    labelShowLunarDate   = new QLabel(widgetRight);
    labelSpacer          = new QLabel(widgetRight);
    labelPlanTitle   = new QLabel(widgetRight);
    labelShowPlan        = new QLabel(widgetRight);

    labelShowToday->setAlignment(Qt::AlignCenter);
    labelShowWeek->setAlignment(Qt::AlignCenter);
    labelShowDay->setAlignment(Qt::AlignCenter);
    labelShowNYear->setAlignment(Qt::AlignCenter);
    labelShowLunarDate->setAlignment(Qt::AlignCenter);
    labelSpacer->setFixedSize(widgetRight->width(), 2);

    labelShowToday->setObjectName("labelCommon");
    labelShowWeek->setObjectName("labelCommon");
    labelShowDay->setObjectName("labelShowDay");
    labelShowNYear->setObjectName("labelCommon");
    labelShowLunarDate->setObjectName("labelCommon");
    labelSpacer->setObjectName("labelSpacer");
    labelPlanTitle->setObjectName("labelCommon");
    labelShowPlan->setObjectName("labelSchedule");

    labelShowToday->setText(QDateTime::currentDateTime().toString("yyyy 年 MM 月 dd日"));
    labelShowWeek->setText(QDate::currentDate().toString("ddd"));
    labelShowDay->setText(QDate::currentDate().toString("dd"));
    labelShowNYear->setText(tr("丙申猴年 壬辰月 甲子日"));
    labelShowLunarDate->setText(tr("农历 三月初六"));
    labelPlanTitle->setText(tr("今日行程安排"));
    labelShowPlan->setText(tr("今天需要完成数据采集工作!"));
    labelShowPlan->setWordWrap(true);

    verlayoutWidgetRight = new QVBoxLayout(widgetRight);
    verlayoutWidgetRight->setContentsMargins(0, 0, 0, 0);
    verlayoutWidgetRight->setSpacing(15);
    verlayoutWidgetRight->addWidget(labelShowToday);
    verlayoutWidgetRight->addWidget(labelShowWeek);
    verlayoutWidgetRight->addWidget(labelShowDay);
    verlayoutWidgetRight->addWidget(labelShowNYear);
    verlayoutWidgetRight->addWidget(labelShowLunarDate);
    verlayoutWidgetRight->addWidget(labelSpacer, 0, Qt::AlignCenter);
    verlayoutWidgetRight->addStretch(1);
    verlayoutWidgetRight->addWidget(labelPlanTitle);
    verlayoutWidgetRight->addWidget(labelShowPlan, 1);
    //! [2]

    horLayoutWidget = new QHBoxLayout();
    horLayoutWidget->addWidget(calendar, 3, Qt::AlignCenter);
    horLayoutWidget->addWidget(widgetRight, 1);

    //! [3]
    groupBoxBottom = new QGroupBox(this);

    labelYearJump = new QLabel(groupBoxBottom);
    labelMonthJump = new QLabel(groupBoxBottom);
    labelDayJump = new QLabel(groupBoxBottom);

    labelYearJump->setMinimumWidth(20);
    labelMonthJump->setMinimumWidth(20);
    labelDayJump->setMinimumWidth(20);

    labelYearJump->setObjectName("labelCommon");
    labelMonthJump->setObjectName("labelCommon");
    labelDayJump->setObjectName("labelCommon");

    labelYearJump->setText(tr("年:"));
    labelMonthJump->setText(tr("月:"));
    labelDayJump->setText(tr("日:"));
    ///////////////////////////////////

    editYearJump = new QLineEdit(groupBoxBottom);
    editMonthJump = new QLineEdit(groupBoxBottom);
    editDayJump = new QLineEdit(groupBoxBottom);

    editYearJump->setMaximumWidth(60);
    editMonthJump->setMaximumWidth(60);
    editDayJump->setMaximumWidth(60);

    editYearJump->setText("2016");
    editMonthJump->setText("1");
    editDayJump->setText("1");
    //////////////////////////////////

    btnDateJump = new QPushButton(groupBoxBottom);
    btnDateJump->setText(tr("跳转至该日期"));

    btnToday = new QPushButton(groupBoxBottom);
    btnToday->setText(tr("返回今天"));

    horLayoutJump = new QHBoxLayout(groupBoxBottom);
    horLayoutJump->setSpacing(10);
    horLayoutJump->addWidget(labelYearJump);
    horLayoutJump->addWidget(editYearJump);

    horLayoutJump->addWidget(labelMonthJump);
    horLayoutJump->addWidget(editMonthJump);

    horLayoutJump->addWidget(labelDayJump);
    horLayoutJump->addWidget(editDayJump);

    horLayoutJump->addStretch(1);
    horLayoutJump->addWidget(btnDateJump);
    horLayoutJump->addWidget(btnToday);

    //! [3]

    //! [4]
    verLayoutAll = new QVBoxLayout(this);
    verLayoutAll->setContentsMargins(10, 10, 10, 10);
    verLayoutAll->setSpacing(10);
    verLayoutAll->addLayout(horLayoutWidget, 1);
    verLayoutAll->addWidget(groupBoxBottom, 0);

    //! [4]
    connect(calendar, SIGNAL(signalDayChanged()), this, SLOT(sltDayChanged()));
    connect(calendar, SIGNAL(signalDayClicked(int)), this, SLOT(sltDayClicked(int)));
    connect(calendar, SIGNAL(signalPlan(QString)), this, SLOT(sltShowPlans(QString)));
    connect(btnDateJump, SIGNAL(clicked(bool)), this, SLOT(sltDateJump()));
    connect(btnToday, SIGNAL(clicked(bool)), this, SLOT(sltBack2today()));
}

void Window::initDatabase()
{
}


/**
 * @brief CalendarWidget::initStyle 初始化样式
 */
void Window::initStyle()
{
    QString strStyle = "";
#ifdef Q_OS_ANDROID
    strStyle += QString(".CalendarWidget {border: 1px solid #ff00ff;}");
    strStyle += QString(".Window {background: black;}");
    strStyle += QString(".DayLabel{font-size: 64px;}");
    strStyle += QString("QWidget#widgetRight{background-color: transparent;}");
    strStyle += QString("QWidget#widgetCalendar{ background-color: white;}");
    strStyle += QString("QWidget#widgetTitle{ background-color: #c8b9a6;}");
    strStyle += QString("QWidget#widgetWeek{ background-color: #efefef;}");
    strStyle += QString("QLabel#labelTitle {border: none; font: bold 18px;}");
    strStyle += QString("QLabel#labelWeek {border-top: 1px solid #c3c3c3; border-left: 1px solid #c3c3c3; font: bold 12px;}");
    strStyle += QString("QLabel#labelDay[weekend=true],QLabel#labelWeek[weekend=true]{color: red;}");
    strStyle += QString("QLabel#labelDay {border-top: 1px solid #c3c3c3; border-left: 1px solid #c3c3c3; font-size: 14px;}");
    strStyle += QString("QLabel#labelShowDay {color: yellow; font: bold 64px;}");
    strStyle += QString("QLabel#labelCommon {background-color: transparent;color: #ffffff;}");
    strStyle += QString("QLabel#labelSchedule {background-color: transparent;color: #ffffff; border: 1px solid #ffffff;}");
    strStyle += QString("QLabel#labelSpacer {border: 1px solid #ffffff;}");
    strStyle += QString("QLineEdit {border: 1px solid #ffffff; border-radius: 5px; font-size: 20px;}");

#else
    strStyle += QString(".CalendarWidget {border: 1px solid #ff00ff;}");
    strStyle += QString(".Window {background: black;}");
    strStyle += QString(".DayLabel{font: 24px; font-family: 隶书;}");
    strStyle += QString("QWidget#widgetCalendar{ background-color: white;}");
    strStyle += QString("QWidget#widgetTitle{ background-color: #c8b9a6;}");
    strStyle += QString("QWidget#widgetWeek{ background-color: #efefef;}");
    strStyle += QString("QLabel#labelTitle {border: none; font: bold 18px;}");
    strStyle += QString("QLabel#labelWeek {border-top: 1px solid #c3c3c3; border-left: 1px solid #c3c3c3; font: bold 12px;}");
    strStyle += QString("QLabel#labelDay[weekend=true],QLabel#labelWeek[weekend=true]{color: red;}");
    strStyle += QString("QLabel#labelDay {border-top: 1px solid #c3c3c3; border-left: 1px solid #c3c3c3; font-size: 14px;}");
    strStyle += QString("QLabel#labelShowDay {color: yellow; font: bold 64px;}");
    strStyle += QString("QLabel#labelCommon {color: #ffffff;}");
    strStyle += QString("QLabel#labelSchedule {color: #ffffff; border: 1px solid #ffffff;}");
    strStyle += QString("QLabel#labelSpacer {border: 1px solid #ffffff;}");
    strStyle += QString("QLineEdit {border: 1px solid #ffffff; border-radius: 5px; font-size: 20px;}");
#endif
    this->setStyleSheet(strStyle);
}

void Window::sltDayClicked(int nday)
{
    labelShowDay->setText(QString("%1").arg(nday, 2, 10, QChar('0')));
    // 显示农历
    QString strLunar = Date::getLunarMonAndDay(calendar->year(), calendar->month(), nday);
    labelShowLunarDate->setText(tr("农历  %1").arg(strLunar));
}

void Window::sltDayChanged()
{
    // 更新右边控件显示
    labelShowDay->setText(QString("%1").arg(calendar->day(), 2, 10, QChar('0')));
    // 显示农历
    QString strLunar = Date::getLunarMonAndDay(calendar->year(), calendar->month(), calendar->day());
    labelShowLunarDate->setText(tr("农历  %1").arg(strLunar));
    labelShowNYear->setText(Date::getLunarTime(calendar->year()));
}

// 跳转日期
void Window::sltDateJump()
{
    int year = editYearJump->text().toInt();
    int month = editMonthJump->text().toInt();
    int day = editDayJump->text().toInt();
    int nMaxSet = 0;

    if ((year > 2040) || (year < 1970)) {
        QMessageBox::information(this, tr("提示"), tr("跳转年输入错误,请重新输入!"));
        editYearJump->setFocus();
        return;
    }

    if ((month > 12) || (month < 1)) {
        editMonthJump->setFocus();
        QMessageBox::information(this, tr("提示"), tr("跳转月输入错误,请重新输入!"));
        return;
    }

    if (2 == month) {
        nMaxSet = Date::isLoopYaer(year) ? 29 : 28;
    }
    else {
        nMaxSet = 31;
    }

    if ((day > nMaxSet) || (day < 1)) {
        editDayJump->setFocus();
        QMessageBox::information(this, tr("提示"), tr("跳转日输入错误,请重新输入!"));
        return;
    }
    // 跳转
    calendar->jumpTodate(year, month, day);
}

/**
 * @brief Window::sltBack2today 跳转至今天
 */
void Window::sltBack2today()
{
    int year = QDate::currentDate().year();
    int month = QDate::currentDate().month();
    int day = QDate::currentDate().day();

    // 跳转
    calendar->jumpTodate(year, month, day);
}

/**
 * @brief Window::sltShowPlans 显示日程
 * @param content
 * @return
 */
void Window::sltShowPlans(const QString &content)
{
    labelShowPlan->setText(content);
}

void Window::paintEvent(QPaintEvent *)
{
    QStyleOption opt;
    opt.init(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

void initDate();private slots: void sltDayClicked(int type, int day); void sltShowPrevMonth(); void sltShowNextMonth();};/////////////////////////////////////////// \brief The Window class/// 万年历///////////////////////////////////////class Window : public QWidget { Q_OBJECTpublic: explicit Window(QWidget *parent = 0); ~Window();private: CalendarWidget *calendar; QWidget *widgetRight; QLabel *labelShowToday; QLabel *labelShowWeek; QLabel *labelShowDay; QLabel *labelShowNYear; QLabel *labelShowLunarDate; QLabel *labelSpacer; QLabel *labelPlanTitle; QLabel *labelShowPlan; QVBoxLayout *verlayoutWidgetRight; QHBoxLayout *horLayoutWidget; // 底部新增时间跳转设置,备注说明 QGroupBox *groupBoxBottom; QLabel *labelYearJump; QLabel *labelMonthJump; QLabel *labelDayJump; QLineEdit *editYearJump; QLineEdit *editMonthJump; QLineEdit *editDayJump; QPushButton *btnDateJump; QPushButton *btnToday; QHBoxLayout *horLayoutJump; QVBoxLayout *verLayoutAll;private: void initWidget(); void initDatabase(); void initStyle();private slots: void sltDayClicked(int nday); void sltDayChanged(); void sltDateJump(); void sltBack2today(); void sltShowPlans(const QString &content);protected: void paintEvent(QPaintEvent *);};#endif // CALENDARWIDGET_H


然后就是农历的算法;

</pre></p><p></p><p><pre name="code" class="cpp">#ifndef DATE_H
#define DATE_H

#include <QObject>

class Date : public QObject
{
    Q_OBJECT



public:
    explicit Date(QObject *parent = 0);

signals:

public slots:

public:
    static quint16 getSpringFestivalDate(int year);

    static int getFirstDayOfWeek(int year, int month);
    static int getTotalMonthDays(int year, int month);
    static int getMonthDays(int year, int month);
    static bool isLoopYaer(int year);
    static QString getLunarDate(int year, int month, int day);
    static QString getLunarMonAndDay(int year, int month, int day);
    // 计算今年是什么年如 :甲子年
    static QString getLunarTime(int year);
private:
    static QString holiday(int month, int day);
    static QString solarTerms(int year, int month, int day);
    static QString lunarFestival(int month, int day);
};

#endif // DATE_H


#include "date.h"

#include <QDebug>


#define T_D_YAER   1924 //  天干地支开始计算年月

//每年春节对应的公历日期
static const int springFestival[] = {
    130,217,206,                                // 1968,1969,1970
    127,215,203,123,211,131,218,207,128,216,    // 1971--1980
    205,125,213,202,220,209,219,217,206,127,    // 1981---1990
    215,204,123,210,131,219,207,128,216,205,    // 1991--2000
    124,212,201,122,209,129,218,207,126,214,    // 2001--2010
    203,123,210,131,219,208,128,216,205,125,    // 2011--2020                                       //2011--2020
    212,201,122,210,129,217,206,126,213,203,    // 2021--2030
    123,211,131,219,208,128,215,204,124,212     // 2031--2040
};

//16--18位表示闰几月,0--12位表示农历每月的数据,高位表示1月,低位表示12月(农历闰月就会多一个月)
static const int  nLunarData[] = {
    461653,1386,2413,                                            // 1968,1969,1970
    330077,1197,2637,268877,3365,531109,2900,2922,398042,2395,   // 1971--1980
    1179,267415,2635,661067,1701,1748,398772,2742,2391,330031,   // 1981---1990
    1175,1611,200010,3749,527717,1452,2742,332397,2350,3222,     // 1991--2000
    268949,3402,3493,133973,1386,464219,605,2349,334123,2709,    // 2001--2010
    2890,267946,2773,592565,1210,2651,395863,1323,2707,265877,   // 2011--2020
    1706,2773,133557,1206,398510,2638,3366,335142,3411,1450,     // 2021 -- 2030
    200042,2413,723293,1197,2637,399947,3365,3410,334676,2906    // 2031 -- 2040
};

static const int chineseTwentyFourData[] = {
    0x95,0xB4,0x96,0xA5,0x96,0x97,0x88,0x78,0x78,0x69,0x78,0x87,     // 1970
    0x96,0xB4,0x96,0xA6,0x97,0x97,0x78,0x79,0x79,0x69,0x78,0x77,     // 1971
    0x96,0xA4,0xA5,0xA5,0xA6,0xA6,0x88,0x88,0x88,0x78,0x87,0x87,     // 1972
    0xA5,0xB5,0x96,0xA5,0xA6,0x96,0x88,0x78,0x78,0x78,0x87,0x87,     // 1973
    0x95,0xB4,0x96,0xA5,0x96,0x97,0x88,0x78,0x78,0x69,0x78,0x87,     // 1974
    0x96,0xB4,0x96,0xA6,0x97,0x97,0x78,0x79,0x78,0x69,0x78,0x77,     // 1975
    0x96,0xA4,0xA5,0xB5,0xA6,0xA6,0x88,0x89,0x88,0x78,0x87,0x87,     // 1976
    0xA5,0xB4,0x96,0xA5,0x96,0x96,0x88,0x88,0x78,0x78,0x87,0x87,     // 1977
    0x95,0xB4,0x96,0xA5,0x96,0x97,0x88,0x78,0x78,0x79,0x78,0x87,     // 1978
    0x96,0xB4,0x96,0xA6,0x96,0x97,0x78,0x79,0x78,0x69,0x78,0x77,     // 1979
    0x96,0xA4,0xA5,0xB5,0xA6,0xA6,0x88,0x88,0x88,0x78,0x87,0x87,     // 1980
    0xA5,0xB4,0x96,0xA5,0xA6,0x96,0x88,0x88,0x78,0x78,0x77,0x87,     // 1981
    0x95,0xB4,0x96,0xA5,0x96,0x97,0x88,0x78,0x78,0x79,0x77,0x87,     // 1982
    0x95,0xB4,0x96,0xA5,0x96,0x97,0x78,0x79,0x78,0x69,0x78,0x77,     // 1983
    0x96,0xB4,0xA5,0xB5,0xA6,0xA6,0x87,0x88,0x88,0x78,0x87,0x87,     // 1984
    0xA5,0xB4,0xA6,0xA5,0xA6,0x96,0x88,0x88,0x78,0x78,0x87,0x87,     // 1985
    0xA5,0xB4,0x96,0xA5,0x96,0x97,0x88,0x78,0x78,0x79,0x77,0x87,     // 1986
    0x95,0xB4,0x96,0xA5,0x96,0x97,0x88,0x79,0x78,0x69,0x78,0x87,     // 1987
    0x96,0xB4,0xA5,0xB5,0xA6,0xA6,0x87,0x88,0x88,0x78,0x87,0x86,     // 1988
    0xA5,0xB4,0xA5,0xA5,0xA6,0x96,0x88,0x88,0x88,0x78,0x87,0x87,     // 1989
    0xA5,0xB4,0x96,0xA5,0x96,0x96,0x88,0x78,0x78,0x79,0x77,0x87,     // 1990
    0x95,0xB4,0x96,0xA5,0x86,0x97,0x88,0x78,0x78,0x69,0x78,0x87,     // 1991
    0x96,0xB4,0xA5,0xB5,0xA6,0xA6,0x87,0x88,0x88,0x78,0x87,0x86,     // 1992
    0xA5,0xB3,0xA5,0xA5,0xA6,0x96,0x88,0x88,0x88,0x78,0x87,0x87,     // 1993
    0xA5,0xB4,0x96,0xA5,0x96,0x96,0x88,0x78,0x78,0x78,0x87,0x87,     // 1994
    0x95,0xB4,0x96,0xA5,0x96,0x97,0x88,0x76,0x78,0x69,0x78,0x87,     // 1995
    0x96,0xB4,0xA5,0xB5,0xA6,0xA6,0x87,0x88,0x88,0x78,0x87,0x86,     // 1996
    0xA5,0xB3,0xA5,0xA5,0xA6,0xA6,0x88,0x88,0x88,0x78,0x87,0x87,     // 1997
    0xA5,0xB4,0x96,0xA5,0x96,0x96,0x88,0x78,0x78,0x78,0x87,0x87,     // 1998
    0x95,0xB4,0x96,0xA5,0x96,0x97,0x88,0x78,0x78,0x69,0x78,0x87,     // 1999
    0x96,0xB4,0xA5,0xB5,0xA6,0xA6,0x87,0x88,0x88,0x78,0x87,0x86,     // 2000
    0xA5,0xB3,0xA5,0xA5,0xA6,0xA6,0x88,0x88,0x88,0x78,0x87,0x87,     // 2001
    0xA5,0xB4,0x96,0xA5,0x96,0x96,0x88,0x78,0x78,0x78,0x87,0x87,     // 2002
    0x95,0xB4,0x96,0xA5,0x96,0x97,0x88,0x78,0x78,0x69,0x78,0x87,     // 2003
    0x96,0xB4,0xA5,0xB5,0xA6,0xA6,0x87,0x88,0x88,0x78,0x87,0x86,     // 2004
    0xA5,0xB3,0xA5,0xA5,0xA6,0xA6,0x88,0x88,0x88,0x78,0x87,0x87,     // 2005
    0xA5,0xB4,0x96,0xA5,0xA6,0x96,0x88,0x88,0x78,0x78,0x87,0x87,     // 2006
    0x95,0xB4,0x96,0xA5,0x96,0x97,0x88,0x78,0x78,0x69,0x78,0x87,     // 2007
    0x96,0xB4,0xA5,0xB5,0xA6,0xA6,0x87,0x88,0x87,0x78,0x87,0x86,     // 2008
    0xA5,0xB3,0xA5,0xB5,0xA6,0xA6,0x88,0x88,0x88,0x78,0x87,0x87,     // 2009
    0xA5,0xB4,0x96,0xA5,0xA6,0x96,0x88,0x88,0x78,0x78,0x87,0x87,     // 2010
    0x95,0xB4,0x96,0xA5,0x96,0x97,0x88,0x78,0x78,0x79,0x78,0x87,     // 2011
    0x96,0xB4,0xA5,0xB5,0xA5,0xA6,0x87,0x88,0x87,0x78,0x87,0x86,     // 2012
    0xA5,0xB3,0xA5,0xB5,0xA6,0xA6,0x87,0x88,0x88,0x78,0x87,0x87,     // 2013
    0xA5,0xB4,0x96,0xA5,0xA6,0x96,0x88,0x88,0x78,0x78,0x87,0x87,     // 2014
    0x95,0xB4,0x96,0xA5,0x96,0x97,0x88,0x78,0x78,0x79,0x77,0x87,     // 2015
    0x95,0xB4,0xA5,0xB4,0xA5,0xA6,0x87,0x88,0x87,0x78,0x87,0x86,     // 2016
    0xA5,0xC3,0xA5,0xB5,0xA6,0xA6,0x87,0x88,0x88,0x78,0x87,0x87,     // 2017
    0xA5,0xB4,0xA6,0xA5,0xA6,0x96,0x88,0x88,0x78,0x78,0x87,0x87,     // 2018
    0xA5,0xB4,0x96,0xA5,0x96,0x96,0x88,0x78,0x78,0x79,0x77,0x87,     // 2019
    0x95,0xB4,0xA5,0xB4,0xA5,0xA6,0x97,0x87,0x87,0x78,0x87,0x86,     // 2020
    0xA5,0xC3,0xA5,0xB5,0xA6,0xA6,0x87,0x88,0x88,0x78,0x87,0x86,     // 2021
    0xA5,0xB4,0xA5,0xA5,0xA6,0x96,0x88,0x88,0x88,0x78,0x87,0x87,     // 2022
    0xA5,0xB4,0x96,0xA5,0x96,0x96,0x88,0x78,0x78,0x79,0x77,0x87,     // 2023
    0x95,0xB4,0xA5,0xB4,0xA5,0xA6,0x97,0x87,0x87,0x78,0x87,0x96,     // 2024
    0xA5,0xC3,0xA5,0xB5,0xA6,0xA6,0x87,0x88,0x88,0x78,0x87,0x86,     // 2025
    0xA5,0xB3,0xA5,0xA5,0xA6,0xA6,0x88,0x88,0x88,0x78,0x87,0x87,     // 2026
    0xA5,0xB4,0x96,0xA5,0x96,0x96,0x88,0x78,0x78,0x78,0x87,0x87,     // 2027
    0x95,0xB4,0xA5,0xB4,0xA5,0xA6,0x97,0x87,0x87,0x78,0x87,0x96,     // 2028
    0xA5,0xC3,0xA5,0xB5,0xA6,0xA6,0x87,0x88,0x88,0x78,0x87,0x86,     // 2029
    0xA5,0xB3,0xA5,0xA5,0xA6,0xA6,0x88,0x88,0x88,0x78,0x87,0x87,     // 2030
    0xA5,0xB4,0x96,0xA5,0x96,0x96,0x88,0x78,0x78,0x78,0x87,0x87,     // 2031
    0x95,0xB4,0xA5,0xB4,0xA5,0xA6,0x97,0x87,0x87,0x78,0x87,0x96,     // 2032
    0xA5,0xC3,0xA5,0xB5,0xA6,0xA6,0x88,0x88,0x88,0x78,0x87,0x86,     // 2033
    0xA5,0xB3,0xA5,0xA5,0xA6,0xA6,0x88,0x78,0x88,0x78,0x87,0x87,     // 2034
    0xA5,0xB4,0x96,0xA5,0xA6,0x96,0x88,0x88,0x78,0x78,0x87,0x87,     // 2035
    0x95,0xB4,0xA5,0xB4,0xA5,0xA6,0x97,0x87,0x87,0x78,0x87,0x96,     // 2036
    0xA5,0xC3,0xA5,0xB5,0xA6,0xA6,0x87,0x88,0x88,0x78,0x87,0x86,     // 2037
    0xA5,0xB3,0xA5,0xA5,0xA6,0xA6,0x88,0x88,0x88,0x78,0x87,0x87      // 2038
};

static const char *s_pchDayName[] =  {
    ("*"),
    ("初一"), ("初二"), ("初三"), ("初四"), ("初五"),
    ("初六"), ("初七"), ("初八"), ("初九"), ("初十"),
    ("十一"), ("十二"), ("十三"), ("十四"), ("十五"),
    ("十六"), ("十七"), ("十八"), ("十九"), ("二十"),
    ("廿一"), ("廿二"), ("廿三"), ("廿四"), ("廿五"),
    ("廿六"), ("廿七"), ("廿八"), ("廿九"), ("三十")
};

/*农历月份名*/
static const char *s_pchMonName[] = {
    ("*"),
    ("正月"), ("二月"), ("三月"), ("四月"),
    ("五月"), ("六月"), ("七月"), ("八月"),
    ("九月"), ("十月"), ("冬月"), ("腊月")
};

// 24节气
static const char *s_pchSolarTerm[] = {
    ("小寒"), ("大寒"), ("立春"), ("雨水"), ("惊蛰"), ("春分"), ("清明"), ("谷雨"),
    ("立夏"), ("小满"), ("芒种"), ("夏至"), ("小暑"), ("大暑"), ("立秋"), ("处暑"),
    ("白露"), ("秋分"), ("寒露"), ("霜降"), ("立冬"), ("小雪"), ("大雪"), ("冬至")
};


// 天干算法
static const char *s_pchTiangan[] = {
    ("甲"), ("乙"), ("丙"), ("丁"), ("戊"),
    ("己"), ("庚"), ("辛"), ("壬"), ("癸"),
};

// 动物属性
static const char *s_pchAnimal[] = {
    ("鼠"), ("牛"), ("虎"), ("兔"), ("龙"), ("蛇"),
    ("马"), ("羊"), ("猴"), ("鸡"), ("狗"), ("猪"),
};

// 地址算法
static const char *s_pchDizhi[] = {
    ("子"), ("丑"), ("寅"), ("卯"), ("辰"), ("巳"),
    ("午"), ("未"), ("申"), ("酉"), ("戌"), ("亥"),
};

/*公历每月前面的天数*/
int monthAdd[] = {
    0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
};


Date::Date(QObject *parent) : QObject(parent)
{

}

/**
 * @brief Date::getSpringFestivalMonth 获取当年春节是几月几日
 * @param year
 * @return
 */
quint16 Date::getSpringFestivalDate(int year)
{
    int nTemp = year - 1968;
    int springFestivalMonth = springFestival[nTemp] / 100;
    int springFestivalDay = springFestival[nTemp] % 100;
    qDebug() << springFestivalMonth << springFestivalDay;

    return (springFestivalMonth << 8) | springFestivalDay;
}

int Date::getFirstDayOfWeek(int year, int month)
{
    int week = 0;
    // 获取当年1月1日是星期几
    week = (year + (year- 1) / 4 -(year - 1) / 100 + (year - 1) / 400) % 7;
    week += getTotalMonthDays(year, month);
    return week % 7;
}

int Date::getTotalMonthDays(int year, int month)
{
    int nDays = 0;
    int nLoopDay = isLoopYaer(year) ? 1 : 0;
    switch (month) {
    case  1: nDays =   0;            break;
    case  2: nDays =  31;            break;
    case  3: nDays =  59 + nLoopDay; break;
    case  4: nDays =  90 + nLoopDay; break;
    case  5: nDays = 120 + nLoopDay; break;
    case  6: nDays = 151 + nLoopDay; break;
    case  7: nDays = 181 + nLoopDay; break;
    case  8: nDays = 212 + nLoopDay; break;
    case  9: nDays = 243 + nLoopDay; break;
    case 10: nDays = 273 + nLoopDay; break;
    case 11: nDays = 304 + nLoopDay; break;
    case 12: nDays = 334 + nLoopDay; break;
    default: nDays = 0; break;
    }
    return nDays;
}

int Date::getMonthDays(int year, int month)
{
    int nDays = 0;
    int nLoopDay = isLoopYaer(year) ? 1 : 0;
    switch (month) {
    case  1: nDays = 31;            break;
    case  2: nDays = 28 + nLoopDay; break;
    case  3: nDays = 31;            break;
    case  4: nDays = 30;            break;
    case  5: nDays = 31;            break;
    case  6: nDays = 30;            break;
    case  7: nDays = 31;            break;
    case  8: nDays = 31;            break;
    case  9: nDays = 30;            break;
    case 10: nDays = 31;            break;
    case 11: nDays = 30;            break;
    case 12: nDays = 31;            break;
    default: nDays = 30;            break;
    }

    return nDays;
}

// 判断是否是闰年
bool Date::isLoopYaer(int year)
{
    return (((0 == (year % 4)) && (0 != (year % 100))) || (0 == (year % 400)));
}

/**
 * @brief Date::getLunarDate 计算农历
 * @param year  年
 * @param month 月
 * @param day 日
 * @return
 */
QString Date::getLunarDate (int year, int month, int day){
    int nTheDate,nIsEnd,nMonTemp,k,n,nBit;
    // 先获取公历节日
    QString strDate = holiday(month, day);
    // 计算24节气
    QString strSolarTerms = solarTerms(year, month, day);

    /*现在计算农历:获得当年春节的公历日期(比如:2015年春节日期为(2月19日)),
            以此为分界点,2.19前面的农历是2014年农历(用2014年农历数据来计算),
            2.19以及之后的日期,农历为2015年农历(用2015年农历数据来计算)。*/
    nMonTemp = year - 1968;
    int springFestivalMonth = springFestival[nMonTemp] / 100;
    int springFestivalDaty = springFestival[nMonTemp] % 100;

    if(month < springFestivalMonth )
    {
        nMonTemp--;
        nTheDate = 365 * 1 + day + monthAdd[month - 1] - 31 * ((springFestival[nMonTemp] / 100) - 1) - springFestival[nMonTemp] % 100 + 1;

        if((!(year % 4)) && (month > 2))
            nTheDate = nTheDate + 1;

        if((!((year - 1) % 4)))
            nTheDate = nTheDate + 1;
    }
    else if (month == springFestivalMonth)
    {
        if (day < springFestivalDaty) {
            nMonTemp--;
            nTheDate = 365 * 1 + day + monthAdd[month - 1] - 31 * ((springFestival[nMonTemp] / 100) - 1) - springFestival[nMonTemp] % 100 + 1;

            if((!(year % 4)) && (month > 2))
                nTheDate = nTheDate + 1;

            if((!((year-1) % 4)))
                nTheDate = nTheDate + 1;
        }
        else {
            nTheDate = day + monthAdd[month - 1] - 31 * ((springFestival[nMonTemp] / 100) - 1) - springFestival[nMonTemp] % 100 + 1;

            if((!(year % 4)) && (month > 2))
                nTheDate = nTheDate + 1;
        }
    }else{
        nTheDate = day + monthAdd[month - 1] - 31 * ((springFestival[nMonTemp] / 100) - 1) - springFestival[nMonTemp] % 100 + 1;
        if((!(year % 4)) && (month > 2))
            nTheDate = nTheDate + 1;
    }
    /*--计算农历天干、地支、月、日---*/
    nIsEnd = 0;

    while(nIsEnd != 1)  {
        if(nLunarData[nMonTemp] < 4095)
            k = 11;
        else
            k = 12;
        n = k;
        while(n >= 0)   {
            // 获取wNongliData(m)的第n个二进制位的值
            nBit = nLunarData[nMonTemp];

            nBit = nBit >> n;
            nBit = nBit % 2;
            if (nTheDate <= (29 + nBit))    {
                nIsEnd = 1;
                break;
            }

            nTheDate = nTheDate - 29 - nBit;
            n = n - 1;
        }

        if(nIsEnd)
            break;

        nMonTemp = nMonTemp + 1;
    }

    // 农历的年月日
    year = 1969 + nMonTemp -1;
    month = k - n + 1;
    day = nTheDate;

    if (k == 12)  {
        if (month == (nLunarData[nMonTemp] / 65536) + 1)
            month = 1 - month;
        else if (month > (nLunarData[nMonTemp] / 65536) + 1)
            month = month - 1;
    }

    // 显示装换的农历
    // only day == 1 ,return month name
    if (1 == day) {
        if(month < 1){
            strDate = "闰" + tr(s_pchMonName[month * -1]);
            return strDate;
        }

        // 公历节日
        if ("" != strDate) return strDate;

        // 计算农历节日
        strDate = lunarFestival(month, day);

        // 如果有节日,直接显示
        if ("" == strDate) {
            // 如果当天不是24节气,显示农历日子
            strDate = strSolarTerms;
            if ("" == strDate) {
                strDate = tr(s_pchMonName[month]);
            }
        }

    } else {
        // 公历节日
        if ("" != strDate) return strDate;

        // 计算农历节日
        strDate = lunarFestival(month, day);
        // 如果有节日,直接显示
        if ("" == strDate) {
            // 如果当天不是24节气,显示农历日子
            strDate = strSolarTerms;
            if ("" == strDate) {
                strDate = tr(s_pchDayName[day]);
            }
        }
    }

    return strDate;
}

/**
 * @brief Date::getLunarMonAndDay 响应点击时的农历显示
 * @param year
 * @param month
 * @param day
 * @return
 */
QString Date::getLunarMonAndDay(int year, int month, int day)
{
    int nTheDate, nIsEnd, nMonTemp, k, n, nBit;
    QString strDate = "";
    /*现在计算农历:获得当年春节的公历日期(比如:2015年春节日期为(2月19日)),
            以此为分界点,2.19前面的农历是2014年农历(用2014年农历数据来计算),
            2.19以及之后的日期,农历为2015年农历(用2015年农历数据来计算)。*/
    nMonTemp = year - 1968;
    int springFestivalMonth = springFestival[nMonTemp] / 100;
    int springFestivalDaty = springFestival[nMonTemp] % 100;

    if(month < springFestivalMonth )
    {
        nMonTemp--;
        nTheDate = 365 * 1 + day + monthAdd[month - 1] - 31 * ((springFestival[nMonTemp] / 100) - 1) - springFestival[nMonTemp] % 100 + 1;

        if((!(year % 4)) && (month > 2))
            nTheDate = nTheDate + 1;

        if((!((year - 1) % 4)))
            nTheDate = nTheDate + 1;
    }
    else if (month == springFestivalMonth)
    {
        if (day < springFestivalDaty) {
            nMonTemp--;
            nTheDate = 365 * 1 + day + monthAdd[month - 1] - 31 * ((springFestival[nMonTemp] / 100) - 1) - springFestival[nMonTemp] % 100 + 1;

            if((!(year % 4)) && (month > 2))
                nTheDate = nTheDate + 1;

            if((!((year-1) % 4)))
                nTheDate = nTheDate + 1;
        }
        else {
            nTheDate = day + monthAdd[month - 1] - 31 * ((springFestival[nMonTemp] / 100) - 1) - springFestival[nMonTemp] % 100 + 1;

            if((!(year % 4)) && (month > 2))
                nTheDate = nTheDate + 1;
        }
    }else{
        nTheDate = day + monthAdd[month - 1] - 31 * ((springFestival[nMonTemp] / 100) - 1) - springFestival[nMonTemp] % 100 + 1;
        if((!(year % 4)) && (month > 2))
            nTheDate = nTheDate + 1;
    }
    /*--计算农历天干、地支、月、日---*/
    nIsEnd = 0;

    while(nIsEnd != 1)  {
        if(nLunarData[nMonTemp] < 4095)
            k = 11;
        else
            k = 12;
        n = k;
        while(n >= 0)   {
            // 获取wNongliData(m)的第n个二进制位的值
            nBit = nLunarData[nMonTemp];

            nBit = nBit >> n;
            nBit = nBit % 2;
            if (nTheDate <= (29 + nBit))    {
                nIsEnd = 1;
                break;
            }

            nTheDate = nTheDate - 29 - nBit;
            n = n - 1;
        }

        if(nIsEnd)
            break;

        nMonTemp = nMonTemp + 1;
    }

    // 农历的年月日
    year = 1969 + nMonTemp -1;
    month = k - n + 1;
    day = nTheDate;

    if (k == 12)  {
        if (month == (nLunarData[nMonTemp] / 65536) + 1)
            month = 1 - month;
        else if (month > (nLunarData[nMonTemp] / 65536) + 1)
            month = month - 1;
    }

    // 显示装换的农历
    // only day == 1 ,return month name
    if (1 == day) {
        if (month < 1){
            strDate = tr("闰") + tr(s_pchMonName[month * -1]);
            return strDate;
        }

        strDate = tr(s_pchMonName[month]);

    } else {
        strDate = tr(s_pchMonName[month]) + tr(s_pchDayName[day]);
    }

    return strDate;
}

/**
 * @brief Date::getLunarTime  计算今年是什么年如 :甲子年
 * @param year
 * @return
 */
QString Date::getLunarTime(int year)
{
    int ntemp = 0;
    // 农历时辰
    QString strTime = "";
    if (year > T_D_YAER) {
        ntemp = year - T_D_YAER;
        strTime.append(tr(s_pchTiangan[ntemp % 10]));
        strTime.append(tr(s_pchDizhi[ntemp % 12]));
        strTime.append(tr(s_pchAnimal[ntemp % 12]));
        strTime.append(tr("年"));
    }

    return strTime;
}


/**
 * @brief Date::holiday 公历假日
 * @param month
 * @param day
 * @return
 */
QString Date::holiday(int month, int day)
{
    int temp = (month << 8) | day;
    QString strHoliday = "";
    switch (temp) {
    case 0x0101: strHoliday = tr("元旦");  break;
    case 0x020E: strHoliday = tr("情人节"); break;
    case 0x0308: strHoliday = tr("妇女节"); break;
    case 0x0401: strHoliday = tr("愚人节"); break;
    case 0x0501: strHoliday = tr("劳动节"); break;
    case 0x0504: strHoliday = tr("青年节"); break;
    case 0x0601: strHoliday = tr("儿童节"); break;
    case 0x0701: strHoliday = tr("建党节"); break;
    case 0x0801: strHoliday = tr("建军节"); break;
    case 0x090A: strHoliday = tr("教师节"); break;
    case 0x0A01: strHoliday = tr("国庆节"); break;
    case 0x0C18: strHoliday = tr("圣诞节"); break;
    default: break;
    }

    return strHoliday;
}

/**
 * @brief Date::chineseTwentyFourDay 计算24节气
 * @param year
 * @param month
 * @param day
 * @return
 */
QString Date::solarTerms(int year, int month, int day){
    int dayTemp = 0;
    int index = (year - 1970) * 12 + month - 1;

    if (day < 15) {
        dayTemp = 15 - day;
        if((chineseTwentyFourData[index] >> 4) == dayTemp)
            return tr(s_pchSolarTerm[2 * (month - 1)]);
        else
            return "";

    } else if (day > 15) {
        dayTemp = day - 15;
        if((chineseTwentyFourData[index] & 0x0f) == dayTemp)
            return tr(s_pchSolarTerm[2 * (month - 1) + 1]);
    }

    return "";
}

/**
 * @brief Date::lunarFestival 农历春节节日
 * @param month
 * @param day
 * @return 节日
 */
QString Date::lunarFestival(int month, int day){
    int temp = (month << 8) | day;
    QString strFestival = "";
    switch (temp) {
    case 0x0101: strFestival = tr("春节");  break;
    case 0x010F: strFestival = tr("元宵节"); break;
    case 0x0202: strFestival = tr("龙抬头"); break;
    case 0x0505: strFestival = tr("端午节"); break;
    case 0x0707: strFestival = tr("七夕节"); break;
    case 0x080F: strFestival = tr("中秋节"); break;
    case 0x0909: strFestival = tr("重阳节"); break;
    case 0x0C08: strFestival = tr("腊八节"); break;
    default: break;
    }

    return strFestival;
}



代码里面我还添加了日程管理,不过未写完,留个位置在那里,以后心情好了在完善,至此核心代码已经完成。


给个源代码的下载地址吧:

http://download.csdn.net/detail/nigoole/9492904


Qt 制作带农历的日历

标签:

原文地址:http://blog.csdn.net/nigoole/article/details/51320239

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!