日历(QCalendarWidget)的使用及风格样式的设置

您所在的位置:网站首页 怎样把日历中的签到去掉 日历(QCalendarWidget)的使用及风格样式的设置

日历(QCalendarWidget)的使用及风格样式的设置

2024-06-13 03:09| 来源: 网络整理| 查看: 265

前言

之前项目中没涉及过日历控件(QCalendarWidget),一般我是用简单的日期编辑器代替,对它的印象只存在于QtDesigner中丑的不行的日历控件。这次我要写类似企业微信的日程(如下图)功能的东西,这个就必须用到日历了(此篇博客只介绍日历的写法)。

有两种方式实现:一是自己全部重写,二呢是,修改Qt自带的控件QCalendarWidget,难易程度我肯定选二个了,不过后续我想自己重写一个日历,这样自己更有自主权。

效果图

这次先把效果图放到前边吧,对比着代码看,更容易讲解。

代码及说明

代码部分参考大佬的博客QT之自定义日历-CSDN博客。

因为用的是Qt自带的日历控件,所以就不用操心基本功能(比如时间的管理),我们只需要将日历控件的外貌设置为我们想要的就行了。

导航栏的重写

日历自带的导航栏真心丑,所以我将原始的导航栏隐藏起来自己又重新写了一个。左右按钮我没设置风格,因为写的是Demo,就犯懒了。

setNavigationBarVisible(false); void MyCalendarWidget::initTopWidget() { QWidget* topWidget = new QWidget(this); topWidget->setObjectName("CalendarTopWidget"); topWidget->setFixedHeight(40); topWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); QHBoxLayout* hboxLayout = new QHBoxLayout; hboxLayout->setContentsMargins(12, 0, 12, 0); hboxLayout->setSpacing(4); m_leftMonthBtn = new QPushButton(this); m_leftMonthBtn->setText(""); m_dataLabel = new QLabel(this); m_leftMonthBtn->setObjectName("CalendarLeftMonthBtn"); m_rightMonthBtn->setObjectName("CalendarRightMonthBtn"); m_dataLabel->setObjectName("CalendarDataLabel"); m_leftMonthBtn->setFixedSize(16, 16); m_rightMonthBtn->setFixedSize(16, 16); hboxLayout->addStretch(); hboxLayout->addWidget(m_leftMonthBtn); hboxLayout->addWidget(m_dataLabel); hboxLayout->addWidget(m_rightMonthBtn); hboxLayout->addStretch(); topWidget->setLayout(hboxLayout); QVBoxLayout *vBodyLayout = qobject_cast(layout()); vBodyLayout->insertWidget(0, topWidget); connect(m_leftMonthBtn,&QPushButton::clicked,this,&MyCalendarWidget::onbtnClicked); connect(m_rightMonthBtn,&QPushButton::clicked,this,&MyCalendarWidget::onbtnClicked); setDataLabelTimeText(selectedDate().year(), selectedDate().month()); } void MyCalendarWidget::onbtnClicked() { QPushButton *senderBtn = qobject_cast(sender()); if (senderBtn == m_leftMonthBtn) { showPreviousMonth(); } else if (senderBtn == m_rightMonthBtn) { showNextMonth(); } } 一些基础设置 

 日历这这样首先设置为中文(setLocale),这为行表头(tHorizontalHeader)的名字的中英文做铺垫:中文就是周几,星期几,英文Monday Mon.之类。我还设置了单选和周六日的风格,这些东西不仅只是表面意思,还有其他的作用。

void MyCalendarWidget::initControl() { //layout()->setSizeConstraint(QLayout::SetFixedSize);//大小不随布局变化,我不需要 setLocale(QLocale(QLocale::Chinese));//设置中文 setNavigationBarVisible(false);//隐藏导航条 setVerticalHeaderFormat(QCalendarWidget::NoVerticalHeader);//去掉列表头 setHorizontalHeaderFormat(QCalendarWidget::LongDayNames);//我想要星期几的行表头 setSelectionMode(QCalendarWidget::SingleSelection);//单选 //设置星期风格 QTextCharFormat format; format.setForeground(QColor(51, 51, 51)); format.setBackground(QColor(247,247,247)); format.setFontFamily("Microsoft YaHei"); format.setFontPointSize(9); format.setFontWeight(QFont::Medium); setWeekdayTextFormat(Qt::Saturday, format); setWeekdayTextFormat(Qt::Sunday, format); initTopWidget(); connect(this, &QCalendarWidget::currentPageChanged, [this](int year, int month){ setDataLabelTimeText(year, month); }); }

先说我上面设置了日历是单选的,这个还有一个深层次的原因:我将选中的矩形改为圆形后,出现了一个问题就是,刚show出来后,在当天圆圈圈住后,前一天被矩形框住了,也就是有两个被选中了,前一天用的样式是原始的,而当天的是我新写的。我不知道什么原因造成的,所以只能将其设为单选解决此问题了。

void MyCalendarWidget::paintCell(QPainter *painter, const QRect &rect, const QDate &date) const { if (date == selectedDate()) { painter->save(); painter->setRenderHint(QPainter::Antialiasing); painter->setPen(Qt::NoPen); painter->setBrush(QColor(118, 178, 224)); painter->drawEllipse(QRect(rect.x()+rect.width()/2-10, rect.y() + rect.height()/2-10, 20, 20)); painter->setPen(QColor(255, 255, 255)); painter->drawText(rect, Qt::AlignCenter, QString::number(date.day())); painter->restore(); } else if (date == QDate::currentDate()) { painter->save(); painter->setRenderHint(QPainter::Antialiasing); painter->setPen(QColor(118, 178, 224)); painter->drawText(rect, Qt::AlignCenter, QString::number(date.day())); painter->restore(); } else if (date < minimumDate() || date > maximumDate()) { qDebug()setPen(Qt::NoPen); painter->setBrush(QColor(249, 249, 249)); painter->drawRect(rect.x(), rect.y() + 3, rect.width(), rect.height() - 6); //painter->drawEllipse(QRect(rect.x()+rect.width()/2-10, rect.y() + rect.height()/2-10, 20, 20)); painter->setPen(QColor(255,0,0)); painter->drawText(rect, Qt::AlignCenter, QString::number(date.day())); painter->restore(); } else { QCalendarWidget::paintCell(painter, rect, date); } } QSS设置 

我在上面曾说道,我通过代码只更改了周六日的风格,这是为什么呢?因为qss中我没找到将周六日红色字体改为正常的语句。然后还有一点指的注意的是:设置了weekday 的format,那么表头的format将无效。(If you also set a weekday text format, this format's foreground and background color will take precedence over the header's format.)所以这就造成我为了将周六日变为正常色,但是我就没办法将表头设为其他色了,有点遗憾。

我看了一点QCalendarWidget的源码,视图部分是QCalendarView控制的,它继承的QTableView;我之前以为QCalendarWidget的表头即为QHeaderView,后来发现不是,QCalendarView将表头隐藏,然后将第一行作为horizontalHeader,第一列作为verticalHeader,涉及到的代码有:

enum { RowCount = 6, ColumnCount = 7, HeaderColumn = 0, HeaderRow = 0, MinimumDayOffset = 1 }; QCalendarView::QCalendarView(QWidget *parent) : QTableView(parent), readOnly(false), validDateClicked(false) { setTabKeyNavigation(false); setShowGrid(false); verticalHeader()->setVisible(false); horizontalHeader()->setVisible(false); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); }

QCalendarWidget QAbstractItemView{ font-size:12px; font-family:Microsoft YaHei; font-weight:500; outline:0px; } QCalendarWidget QAbstractItemView:disabled{ color:#D3D3D3; } QCalendarWidget QAbstractItemView:enabled{ color:#333333; } QCalendarView#qt_calendar_calendarview { background-color: #F7F7F7; /*背景色*/ alternate-background-color:#F7F7F7; {/* 表头的背景颜色,为什么设置这个就有效,我不清楚*/ }

为了更好地写qss,我学会了一个dump方法,这样可以看到控件的结构和objectName.

ui->calendarWidget->dumpObjectTree();

 将打印出如下结果:

QCalendarWidget::calendarWidget QVBoxLayout:: QCalendarModel:: QCalendarView::qt_calendar_calendarview QWidget::qt_scrollarea_viewport QWidget::qt_scrollarea_hcontainer QScrollBar:: QBoxLayout:: QWidget::qt_scrollarea_vcontainer QScrollBar:: QBoxLayout:: QStyledItemDelegate:: QHeaderView:: QWidget::qt_scrollarea_viewport QWidget::qt_scrollarea_hcontainer QScrollBar:: QBoxLayout:: QWidget::qt_scrollarea_vcontainer QScrollBar:: QBoxLayout:: QItemSelectionModel:: QHeaderView:: QWidget::qt_scrollarea_viewport QWidget::qt_scrollarea_hcontainer QScrollBar:: QBoxLayout:: QWidget::qt_scrollarea_vcontainer QScrollBar:: QBoxLayout:: QItemSelectionModel:: QTableCornerButton:: QItemSelectionModel:: QWidget::qt_calendar_navigationbar QPrevNextCalButton::qt_calendar_prevmonth QPrevNextCalButton::qt_calendar_nextmonth QToolButton::qt_calendar_monthbutton QMenu:: QAction:: QAction:: QAction:: QAction:: QAction:: QAction:: QAction:: QAction:: QAction:: QAction:: QAction:: QAction:: QAction:: QToolButton::qt_calendar_yearbutton QSpinBox::qt_calendar_yearedit QLineEdit::qt_spinbox_lineedit QWidgetLineControl:: QValidator::qt_spinboxvalidator QHBoxLayout:: QCalendarDelegate:: QCalendarTextNavigator:: QProxyStyle:: QWidget::CalendarTopWidget QHBoxLayout:: QPushButton::CalendarLeftMonthBtn QLabel::CalendarDataLabel QPushButton::CalendarRightMonthBtn

结束语

好了,下班了,就这样了,周末愉快。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3