当前位置: 首页 > news >正文

界面开发框架Qt新手入门指南 - 使用Calendar组件创建日历(一)

Qt是目前最先进、最完整的跨平台C++开发工具。它不仅完全实现了一次编写,所有平台无差别运行,更提供了几乎所有开发过程中需要用到的工具。如今,Qt已被运用于超过70个行业、数千家企业,支持数百万设备及应用。

本文中的CalendarWidget示例展示了QCalendarWidget的用法。

QCalendarWidget一次显示一个日历月,并允许用户选择一个日期。日历由四个组件组成:一个允许用户更改显示月份的导航栏、一个网格,其中每个单元格表示一个月中的一天,以及两个显示星期名称和星期数字的标题。

Calendar Widget示例显示一个QCalendarWidget,并允许用户使用QComboBoxes、QCheckBoxes和QDateEdits配置其外观和操作,此外,用户可以影响单个日期和标题的格式。

QCalendarWidget的属性总结如下:

  • selectedDate:当前选择的日期。
  • minimumDate:可以选择的最早日期。
  • maximumDate:可以选择的最晚日期。
  • firstDayOfWeek:显示为一周的第一天的日期(通常是星期日或星期一)。
  • gridVisible:是否显示网格。
  • selectionMode:用户是否可以选择日期。
  • horizontalHeaderFormat:水平标题中日期名称的格式(例如,"M", "Mon"或"Monday")。
  • verticalHeaderFormat:垂直页眉的格式。
  • navigationBarVisible:是否显示日历小部件顶部的导航栏。

本示例包含一个类Window,它创建并布局QCalendarWidget和其他让用户配置QCalendarWidget的小部件。

窗口类定义

下面是Window类的定义:

class Window : public QWidget { Q_OBJECT public: Window(QWidget *parent = nullptr); private slots: void localeChanged(int index); void firstDayChanged(int index); void selectionModeChanged(int index); void horizontalHeaderChanged(int index); void verticalHeaderChanged(int index); void selectedDateChanged(); void minimumDateChanged(QDate date); void maximumDateChanged(QDate date); void weekdayFormatChanged(); void weekendFormatChanged(); void reformatHeaders(); void reformatCalendarPage(); private: void createPreviewGroupBox(); void createGeneralOptionsGroupBox(); void createDatesGroupBox(); void createTextFormatsGroupBox(); QComboBox *createColorComboBox(); QGroupBox *previewGroupBox; QGridLayout *previewLayout; QCalendarWidget *calendar; QGroupBox *generalOptionsGroupBox; QLabel *localeLabel; QLabel *firstDayLabel; ... QCheckBox *mayFirstCheckBox; };

与表示自包含窗口的类一样,大多数API都是私有的。当我们在执行过程中偶然发现私人成员时,将对其进行审查。

窗口类实现

现在让我们回顾一下类的实现,从构造函数开始:

Window::Window(QWidget *parent) : QWidget(parent) { createPreviewGroupBox(); createGeneralOptionsGroupBox(); createDatesGroupBox(); createTextFormatsGroupBox(); QGridLayout *layout = new QGridLayout; layout->addWidget(previewGroupBox, 0, 0); layout->addWidget(generalOptionsGroupBox, 0, 1); layout->addWidget(datesGroupBox, 1, 0); layout->addWidget(textFormatsGroupBox, 1, 1); layout->setSizeConstraint(QLayout::SetFixedSize); setLayout(layout); previewLayout->setRowMinimumHeight(0, calendar->sizeHint().height()); previewLayout->setColumnMinimumWidth(0, calendar->sizeHint().width()); setWindowTitle(tr("Calendar Widget")); }

我们首先使用四个私有的create…GroupBox()函数创建四个qgroupbox及其子部件(包括QCalendarWidget),如下所述,然后在QGridLayout中安排组框。

我们将网格布局的调整大小策略设置为QLayout::SetFixedSize,以防止用户调整窗口大小。在这种模式下,窗口的大小由QGridLayout根据其内容小部件的大小提示自动设置。

为了确保在每次更改QCalendarWidget的属性(例如,隐藏导航栏、垂直标题或网格)时不会自动调整窗口的大小,我们将第0行的最小高度和第0列的最小宽度设置为QCalendarWidget的初始大小。

让我们来看看createPreviewGroupBox()函数:

void Window::createPreviewGroupBox() { previewGroupBox = new QGroupBox(tr("Preview")); calendar = new QCalendarWidget; calendar->setMinimumDate(QDate(1900, 1, 1)); calendar->setMaximumDate(QDate(3000, 1, 1)); calendar->setGridVisible(true); connect(calendar, &QCalendarWidget::currentPageChanged, this, &Window::reformatCalendarPage); previewLayout = new QGridLayout; previewLayout->addWidget(calendar, 0, 0, Qt::AlignCenter); previewGroupBox->setLayout(previewLayout); }

Preview组框只包含一个小部件:QCalendarWidget,我们设置它,将它的currentPageChanged()信号连接到reformatCalendarPage()插槽,以确保每个新页面都获得用户指定的格式。

createGeneralOptionsGroupBox()函数有点大,并且以相同的方式设置了几个小部件。我们将在这里查看它的部分实现,并跳过其余部分:

void Window::createGeneralOptionsGroupBox() { generalOptionsGroupBox = new QGroupBox(tr("General Options")); localeCombo = new QComboBox; int curLocaleIndex = -1; int index = 0; for (int _lang = QLocale::C; _lang <= QLocale::LastLanguage; ++_lang) { QLocale::Language lang = static_cast<QLocale::Language>(_lang); const auto locales = QLocale::matchingLocales(lang, QLocale::AnyScript, QLocale::AnyTerritory); for (auto loc : locales) { QString label = QLocale::languageToString(lang); auto territory = loc.territory(); label += QLatin1Char('/'); label += QLocale::territoryToString(territory); if (locale().language() == lang && locale().territory() == territory) curLocaleIndex = index; localeCombo->addItem(label, loc); ++index; } } if (curLocaleIndex != -1) localeCombo->setCurrentIndex(curLocaleIndex); localeLabel = new QLabel(tr("&Locale")); localeLabel->setBuddy(localeCombo); firstDayCombo = new QComboBox; firstDayCombo->addItem(tr("Sunday"), Qt::Sunday); firstDayCombo->addItem(tr("Monday"), Qt::Monday); firstDayCombo->addItem(tr("Tuesday"), Qt::Tuesday); firstDayCombo->addItem(tr("Wednesday"), Qt::Wednesday); firstDayCombo->addItem(tr("Thursday"), Qt::Thursday); firstDayCombo->addItem(tr("Friday"), Qt::Friday); firstDayCombo->addItem(tr("Saturday"), Qt::Saturday); firstDayLabel = new QLabel(tr("Wee&k starts on:")); firstDayLabel->setBuddy(firstDayCombo); ...

我们从组合框上的周开始设置开始,此组合框控制哪一天应显示为一周的第一天。

QComboBox类允许我们将用户数据作为QVariant附加到每个项目,稍后可以使用QComboBox的itemData()函数检索数据。QVariant不直接支持Qt::DayOfWeek数据类型,但它支持int, c++会很乐意将任何enum值转换为int。

... connect(localeCombo, &QComboBox::currentIndexChanged, this, &Window::localeChanged); connect(firstDayCombo, &QComboBox::currentIndexChanged, this, &Window::firstDayChanged); connect(selectionModeCombo, &QComboBox::currentIndexChanged, this, &Window::selectionModeChanged); connect(gridCheckBox, &QCheckBox::toggled, calendar, &QCalendarWidget::setGridVisible); connect(navigationCheckBox, &QCheckBox::toggled, calendar, &QCalendarWidget::setNavigationBarVisible); connect(horizontalHeaderCombo, &QComboBox::currentIndexChanged, this, &Window::horizontalHeaderChanged); connect(verticalHeaderCombo, &QComboBox::currentIndexChanged, this, &Window::verticalHeaderChanged); ...

在创建了小部件之后,我们连接信号和插槽,将组合框连接到Window的私有槽或QComboBox提供的公共槽。

... firstDayChanged(firstDayCombo->currentIndex()); selectionModeChanged(selectionModeCombo->currentIndex()); horizontalHeaderChanged(horizontalHeaderCombo->currentIndex()); verticalHeaderChanged(verticalHeaderCombo->currentIndex()); }

在函数的最后,我们调用更新日历的槽,以确保QCalendarWidget在启动时与其他小部件同步。

在下文中,我们将继续介绍更多实现窗口类的函数,欢迎持续关注哦~

http://www.cnnetsun.cn/news/3970679.html

相关文章:

  • 深入理解Claude的终端启动参数‌的使用教程
  • 2026肇庆危房鉴定检测怎么选?老旧房危房鉴定靠谱机构 TOP 结构安全检测+ 报告可查 电话汇总
  • 从Excel到专业项目管理平台,研发团队效率提升的真实案例
  • 【微服务实战之Docker容器】-入门学习第一课
  • SpringBoot项目实战(1):SpringBoot介绍
  • 江苏汉软MES系统应用于铜网行业
  • PyTorch 训练流程优化与分布式训练实践:让结论进入下一次检查清单
  • 从 MVP 到规模化落地的项目管理实践:让结论进入下一次检查清单
  • YOLO果园无花果目标检测数据集-324张
  • 成都燃气灶维修全域覆盖 欧米到家同城上门深度检修承诺不返工|打不着火|松手熄火|黄火冒黑烟|漏气|各类故障一站式解决
  • requests.post(url,json,headers,timeout)函数参数json、data、parameter的区别
  • 5分钟免费解锁Office高级功能:Ohook开源工具的完整指南
  • FDE一天到底在干什么——前沿部署工程师的真实工作内容拆解
  • 5个实用技巧彻底解锁Wand专业版功能:告别时间限制的终极指南
  • 2026最新:苹果用户怎么选语音转文字?3款实用免费工具亲测推荐
  • 研究生做论文整理:2026年5款图片转文字app推荐,免费额度满足日常需求
  • Prompt-Region Grounding:为什么把题目画进图片,多模态大模型就集体“不会做题“了
  • 专属新品首发专区,2027具身智能展官方预定
  • 西湖论剑:网络安全领域的“华山论剑”
  • 5分钟掌握暗黑破坏神2存档编辑:可视化修改角色与装备的完整方案
  • 3个步骤解锁星露谷物语的无限可能:SMAPI模组加载器深度解析
  • 2026年语音转文字神器实测对比:哪款好用,差距竟然这么大
  • 登报召开股东大会公告怎么登?股东大会登报公告办理渠道与注意事项
  • 无锡燃气灶维修全域覆盖 欧米到家同城上门深度检修承诺不返工|打不着火|松手熄火|黄火冒黑烟|漏气|各类故障一站式解决
  • 终极PS Vita内容管理指南:如何用开源工具QCMA实现无线备份自由
  • 基于51单片机与DS18B20的智能温控风扇系统设计与实践
  • 【单片机课设毕设项目】基于 STM32 单片机的阈值可调型温室环境智能调控装置 基于 51 单片机的声光报警式农田小型环境智能管控系统(017702)
  • SSH远程Vim文本复制到本地剪贴板的终极方案:OSC 52原理与配置详解
  • 实证论文缺核心变量?
  • 动态肩部平衡:提升网球高尔夫击球效率与预防损伤的生物力学解析