一、前言
農曆控件在國産linux中必備的控件之一,畢竟要适應國人的習慣,你看win10系統的月曆,現在點開來直接就有農曆在上面,非常友善人性化,是以在很多用Qt做的項目中,也有農曆控件的應用場景,而Qt自帶的月曆控件比較簡單,仔細看過源碼的人也隻知道,其實就是一堆微調框,下拉框,表格組成的,于是打算借用此方法造一個農曆控件,本控件的算法是倪大俠提供的,個人測試下來還是沒有問題的,造這個農曆控件最大的難點是如何根據日期計算農曆時間,再加上一些農曆的節氣之類的,這個網上估計也有很多的算法參考。
主要功能:
- 可設定邊框顔色/周末顔色/角标顔色/農曆節日顔色
- 可設定目前月文字顔色/其他月文字顔色/選中日期文字顔色/懸停日期文字顔色
- 可設定目前月農曆文字顔色/其他月農曆文字顔色/選中日期農曆文字顔色/懸停日期農曆文字顔色
- 可設定目前月背景顔色/其他月背景顔色/選中日期背景顔色/懸停日期背景顔色
- 可設定三種選中背景模式,矩形背景+圓形背景+圖檔背景
- 可直接切換到上一年/下一年/上一月/下一月/轉到今天
- 可設定是否顯示農曆資訊,不顯示則當做正常的月曆使用
- 支援1900年-2099年範圍
- 很友善改成多選日期
二、代碼思路
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();
}
三、效果圖
四、開源首頁
以上作品完整源碼下載下傳都在開源首頁,會持續不斷更新作品數量和品質,歡迎各位關注。