Exemple de widget de calendrier
L'exemple de widget de calendrier illustre l'utilisation de QCalendarWidget.

QCalendarWidget Il affiche un mois à la fois et permet à l'utilisateur de sélectionner une date. Le calendrier se compose de quatre éléments : une barre de navigation permettant à l'utilisateur de changer le mois affiché, une grille dont chaque cellule représente un jour du mois, et deux en-têtes affichant les noms des jours de la semaine et les numéros de semaine.
L'exemple de widget Calendrier affiche un QCalendarWidget et permet à l'utilisateur de configurer son apparence et son comportement à l'aide d'QComboBox, d'QCheckBoxet d'QDateEdit. De plus, l'utilisateur peut modifier la mise en forme des dates et des en-têtes individuels.
Les propriétés de l’ QCalendarWidget sont récapitulées dans le tableau ci-dessous.
| Propriété | Description |
|---|---|
| selectedDate | Date actuellement sélectionnée. |
| minimumDate | La date la plus ancienne pouvant être sélectionnée. |
| maximumDate | La date la plus récente pouvant être sélectionnée. |
| firstDayOfWeek | Le jour affiché comme premier jour de la semaine (généralement le dimanche ou le lundi). |
| gridVisible | Si la grille doit être affichée. |
| selectionMode | Si l'utilisateur peut ou non sélectionner une date. |
| horizontalHeaderFormat | Le format des noms de jours dans l'en-tête horizontal (par exemple, « M », « Mon » ou « lundi »). |
| verticalHeaderFormat | Le format de l'en-tête vertical. |
| navigationBarVisible | Si la barre de navigation en haut du widget de calendrier doit s'afficher. |
L'exemple se compose d'une seule classe, Window, qui crée et met en page l'QCalendarWidget ainsi que les autres widgets permettant à l'utilisateur de configurer l'QCalendarWidget.
Définition de la classe Window
Voici la définition de la classe ` 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;
};Comme c’est souvent le cas pour les classes représentant des fenêtres autonomes, la majeure partie de l’API est privée. Nous passerons en revue les membres privés au fur et à mesure que nous les rencontrerons dans l’implémentation.
Implémentation de la classe Window
Passons maintenant en revue l’implémentation de la classe, en commençant par le constructeur :
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"));
}Nous commençons par créer les quatre objets ` QGroupBox` et leurs widgets enfants (y compris l'QCalendarWidget) à l'aide de quatre fonctions privées ` create...GroupBox() `, décrites ci-dessous. Ensuite, nous organisons les zones de groupe dans une disposition en grille ( QGridLayout).
Nous définissons la politique de redimensionnement de la disposition en grille sur « QLayout::SetFixedSize » afin d’empêcher l’utilisateur de redimensionner la fenêtre. Dans ce mode, la taille de la fenêtre est définie automatiquement par « QGridLayout » en fonction des indications de taille de ses widgets de contenu.
Pour garantir que la fenêtre ne soit pas automatiquement redimensionnée à chaque fois que nous modifions une propriété de l’ QCalendarWidget (par exemple, en masquant la barre de navigation, l’en-tête vertical ou la grille), nous définissons la hauteur minimale de la ligne 0 et la largeur minimale de la colonne 0 à la taille initiale de l’ QCalendarWidget.
Passons maintenant à la fonction ` 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);
}La zone de groupe « Preview » ne contient qu’un seul widget : l’ QCalendarWidget. Nous le configurons, puis connectons son signal « currentPageChanged() » à notre slot « reformatCalendarPage() » afin de garantir que chaque nouvelle page adopte la mise en forme spécifiée par l’utilisateur.
La fonction ` createGeneralOptionsGroupBox() ` est assez longue et plusieurs widgets sont configurés de la même manière. Nous allons examiner ici certaines parties de son implémentation et passer le reste :
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);
...Nous commencerons par la configuration de la liste déroulante d’ Week starts on. Cette liste permet de choisir quel jour doit être affiché comme premier jour de la semaine.
La classe ` QComboBox ` nous permet d’associer des données utilisateur sous forme d’ QVariant s à chaque élément. Ces données peuvent ensuite être récupérées à l’aide de la fonction ` itemData()` de ` QComboBox`. ` QVariant ` ne prend pas directement en charge le type de données ` Qt::DayOfWeek `, mais il prend en charge ` int`, et C++ se chargera volontiers de convertir toute valeur d’énumération en ` 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);
...Après avoir créé les widgets, nous connectons les signaux et les slots. Nous connectons les listes déroulantes aux slots privés de Window ou aux slots publics fournis par QComboBox.
...
firstDayChanged(firstDayCombo->currentIndex());
selectionModeChanged(selectionModeCombo->currentIndex());
horizontalHeaderChanged(horizontalHeaderCombo->currentIndex());
verticalHeaderChanged(verticalHeaderCombo->currentIndex());
}À la fin de la fonction, nous appelons les slots qui mettent à jour le calendrier afin de garantir que l’ QCalendarWidget soit synchronisé avec les autres widgets au démarrage.
Examinons maintenant la fonction privée de ` createDatesGroupBox() ` :
void Window::createDatesGroupBox()
{
datesGroupBox = new QGroupBox(tr("Dates"));
minimumDateEdit = new QDateEdit;
minimumDateEdit->setDisplayFormat("MMM d yyyy");
minimumDateEdit->setDateRange(calendar->minimumDate(),
calendar->maximumDate());
minimumDateEdit->setDate(calendar->minimumDate());
minimumDateLabel = new QLabel(tr("&Minimum Date:"));
minimumDateLabel->setBuddy(minimumDateEdit);
currentDateEdit = new QDateEdit;
currentDateEdit->setDisplayFormat("MMM d yyyy");
currentDateEdit->setDate(calendar->selectedDate());
currentDateEdit->setDateRange(calendar->minimumDate(),
calendar->maximumDate());
currentDateLabel = new QLabel(tr("&Current Date:"));
currentDateLabel->setBuddy(currentDateEdit);
maximumDateEdit = new QDateEdit;
maximumDateEdit->setDisplayFormat("MMM d yyyy");
maximumDateEdit->setDateRange(calendar->minimumDate(),
calendar->maximumDate());
maximumDateEdit->setDate(calendar->maximumDate());
maximumDateLabel = new QLabel(tr("Ma&ximum Date:"));
maximumDateLabel->setBuddy(maximumDateEdit);Dans cette fonction, nous créons les widgets d’édition Minimum Date, Maximum Date et Current Date, qui contrôlent respectivement les dates minimale, maximale et sélectionnée du calendrier. Les dates minimale et maximale du calendrier ont déjà été définies dans createPrivewGroupBox(); nous pouvons donc attribuer aux widgets les valeurs par défaut correspondant à celles du calendrier.
connect(currentDateEdit, &QDateEdit::dateChanged,
calendar, &QCalendarWidget::setSelectedDate);
connect(calendar, &QCalendarWidget::selectionChanged,
this, &Window::selectedDateChanged);
connect(minimumDateEdit, &QDateEdit::dateChanged,
this, &Window::minimumDateChanged);
connect(maximumDateEdit, &QDateEdit::dateChanged,
this, &Window::maximumDateChanged);
...
}Nous connectons le signal dateChanged() de l’ currentDateEdit directement au slot setSelectedDate() du calendrier. Lorsque la date sélectionnée du calendrier change, que ce soit à la suite d’une action de l’utilisateur ou par programmation, notre slot selectedDateChanged() met à jour l’éditeur Current Date. Nous devons également réagir lorsque l’utilisateur modifie les éditeurs Minimum Date et Maximum Date.
Voici la fonction createTextFormatsGroup():
void Window::createTextFormatsGroupBox()
{
textFormatsGroupBox = new QGroupBox(tr("Text Formats"));
weekdayColorCombo = createColorComboBox();
weekdayColorCombo->setCurrentIndex(
weekdayColorCombo->findText(tr("Black")));
weekdayColorLabel = new QLabel(tr("&Weekday color:"));
weekdayColorLabel->setBuddy(weekdayColorCombo);
weekendColorCombo = createColorComboBox();
weekendColorCombo->setCurrentIndex(
weekendColorCombo->findText(tr("Red")));
weekendColorLabel = new QLabel(tr("Week&end color:"));
weekendColorLabel->setBuddy(weekendColorCombo);Nous avons configuré les listes déroulantes « Weekday Color » et « Weekend Color » à l'aide de createColorCombo(), qui instancie un objet QComboBox et le remplit avec des couleurs (« Red », « Blue », etc.).
headerTextFormatCombo = new QComboBox;
headerTextFormatCombo->addItem(tr("Bold"));
headerTextFormatCombo->addItem(tr("Italic"));
headerTextFormatCombo->addItem(tr("Plain"));
headerTextFormatLabel = new QLabel(tr("&Header text:"));
headerTextFormatLabel->setBuddy(headerTextFormatCombo);
firstFridayCheckBox = new QCheckBox(tr("&First Friday in blue"));
mayFirstCheckBox = new QCheckBox(tr("May &1 in red"));La liste déroulante Header Text Format permet à l'utilisateur de modifier le format de texte (gras, italique ou normal) utilisé pour les en-têtes horizontaux et verticaux. Les cases à cocher First Friday in blue et May 1 in red influencent l'affichage de dates spécifiques.
connect(weekdayColorCombo, &QComboBox::currentIndexChanged,
this, &Window::weekdayFormatChanged);
connect(weekdayColorCombo, &QComboBox::currentIndexChanged,
this, &Window::reformatCalendarPage);
connect(weekendColorCombo, &QComboBox::currentIndexChanged,
this, &Window::weekendFormatChanged);
connect(weekendColorCombo, &QComboBox::currentIndexChanged,
this, &Window::reformatCalendarPage);
connect(headerTextFormatCombo, &QComboBox::currentIndexChanged,
this, &Window::reformatHeaders);
connect(firstFridayCheckBox, &QCheckBox::toggled,
this, &Window::reformatCalendarPage);
connect(mayFirstCheckBox, &QCheckBox::toggled,
this, &Window::reformatCalendarPage);Nous connectons les cases à cocher et les listes déroulantes à divers slots privés. Les cases à cocher « First Friday in blue » et « May 1 in red » sont toutes deux connectées à « reformatCalendarPage() », qui est également appelé lorsque le calendrier change de mois.
...
reformatHeaders();
reformatCalendarPage();
}À la fin de ` createTextFormatsGroupBox()`, nous appelons des slots privés pour synchroniser ` QCalendarWidget ` avec les autres widgets.
Nous avons maintenant terminé l’examen des quatre fonctions de create...GroupBox(). Examinons à présent les autres fonctions et slots privés.
QComboBox *Window::createColorComboBox()
{
QComboBox *comboBox = new QComboBox;
comboBox->addItem(tr("Red"), QColor(Qt::red));
comboBox->addItem(tr("Blue"), QColor(Qt::blue));
comboBox->addItem(tr("Black"), QColor(Qt::black));
comboBox->addItem(tr("Magenta"), QColor(Qt::magenta));
return comboBox;
}Dans ` createColorCombo()`, nous créons une liste déroulante et la remplissons avec des couleurs standard. Le deuxième argument de ` QComboBox::addItem()` est un ` QVariant ` contenant les données utilisateur (dans ce cas, des objets ` QColor `).
Cette fonction a servi à configurer les listes déroulantes Weekday Color et Weekend Color.
void Window::firstDayChanged(int index)
{
calendar->setFirstDayOfWeek(Qt::DayOfWeek(
firstDayCombo->itemData(index).toInt()));
}Lorsque l’utilisateur modifie la valeur de la liste déroulante « Week starts on », la méthode « firstDayChanged() » est appelée avec l’index de la nouvelle valeur de la liste déroulante. Nous récupérons l’élément de données personnalisé associé au nouvel élément courant à l’aide de « itemData() » et le convertissons en « Qt::DayOfWeek ».
selectionModeChanged()Les méthodes ` horizontalHeaderChanged()` et ` verticalHeaderChanged() ` sont très similaires à ` firstDayChanged()` ; elles sont donc omises.
void Window::selectedDateChanged()
{
currentDateEdit->setDate(calendar->selectedDate());
}La méthode selectedDateChanged() met à jour l’éditeur Current Date afin de refléter l’état actuel de QCalendarWidget.
void Window::minimumDateChanged(QDate date)
{
calendar->setMinimumDate(date);
maximumDateEdit->setDate(calendar->maximumDate());
}Lorsque l’utilisateur modifie la date minimale, nous en informons le `QCalendarWidget`. Nous mettons également à jour l’éditeur ` Maximum Date `, car si la nouvelle date minimale est postérieure à la date maximale actuelle, ` QCalendarWidget ` adaptera automatiquement sa date maximale afin d’éviter toute contradiction.
void Window::maximumDateChanged(QDate date)
{
calendar->setMaximumDate(date);
minimumDateEdit->setDate(calendar->minimumDate());
}maximumDateChanged() est implémenté de manière similaire à minimumDateChanged().
void Window::weekdayFormatChanged()
{
QTextCharFormat format;
format.setForeground(qvariant_cast<QColor>(
weekdayColorCombo->itemData(weekdayColorCombo->currentIndex())));
calendar->setWeekdayTextFormat(Qt::Monday, format);
calendar->setWeekdayTextFormat(Qt::Tuesday, format);
calendar->setWeekdayTextFormat(Qt::Wednesday, format);
calendar->setWeekdayTextFormat(Qt::Thursday, format);
calendar->setWeekdayTextFormat(Qt::Friday, format);
}Chaque élément de la liste déroulante dispose d’un objet ` QColor ` comme données utilisateur, correspondant au texte de l’élément. Après avoir récupéré les couleurs des listes déroulantes, nous définissons le format de texte de chaque jour de la semaine.
Le format de texte d'une colonne du calendrier est défini via un objet ` QTextCharFormat`, qui, outre la couleur de premier plan, permet de spécifier diverses informations de mise en forme des caractères. Dans cet exemple, nous ne présentons qu'un sous-ensemble des possibilités.
void Window::weekendFormatChanged()
{
QTextCharFormat format;
format.setForeground(qvariant_cast<QColor>(
weekendColorCombo->itemData(weekendColorCombo->currentIndex())));
calendar->setWeekdayTextFormat(Qt::Saturday, format);
calendar->setWeekdayTextFormat(Qt::Sunday, format);
}weekendFormatChanged() est identique à ` weekdayFormatChanged()`, à la différence qu’il s’applique au samedi et au dimanche au lieu du lundi au vendredi.
void Window::reformatHeaders()
{
QString text = headerTextFormatCombo->currentText();
QTextCharFormat format;
if (text == tr("Bold"))
format.setFontWeight(QFont::Bold);
else if (text == tr("Italic"))
format.setFontItalic(true);
else if (text == tr("Green"))
format.setForeground(Qt::green);
calendar->setHeaderTextFormat(format);
}La méthode ` reformatHeaders() ` est appelée lorsque l’utilisateur modifie le format de texte des en-têtes. Nous comparons le texte actuel de la liste déroulante ` Header Text Format ` afin de déterminer quel format appliquer. (Une alternative aurait consisté à stocker les valeurs ` QTextCharFormat ` en même temps que les éléments de la liste déroulante.)
void Window::reformatCalendarPage()
{
QTextCharFormat mayFirstFormat;
const QDate mayFirst(calendar->yearShown(), 5, 1);
QTextCharFormat firstFridayFormat;
QDate firstFriday(calendar->yearShown(), calendar->monthShown(), 1);
while (firstFriday.dayOfWeek() != Qt::Friday)
firstFriday = firstFriday.addDays(1);
if (firstFridayCheckBox->isChecked()) {
firstFridayFormat.setForeground(Qt::blue);
} else { // Revert to regular colour for this day of the week.
Qt::DayOfWeek dayOfWeek(static_cast<Qt::DayOfWeek>(firstFriday.dayOfWeek()));
firstFridayFormat.setForeground(calendar->weekdayTextFormat(dayOfWeek).foreground());
}
calendar->setDateTextFormat(firstFriday, firstFridayFormat);
// When it is checked, "May First in Red" always takes precedence over "First Friday in Blue".
if (mayFirstCheckBox->isChecked()) {
mayFirstFormat.setForeground(Qt::red);
} else if (!firstFridayCheckBox->isChecked() || firstFriday != mayFirst) {
// We can now be certain we won't be resetting "May First in Red" when we restore
// may 1st's regular colour for this day of the week.
Qt::DayOfWeek dayOfWeek(static_cast<Qt::DayOfWeek>(mayFirst.dayOfWeek()));
calendar->setDateTextFormat(mayFirst, calendar->weekdayTextFormat(dayOfWeek));
}
calendar->setDateTextFormat(mayFirst, mayFirstFormat);
}Dans ` reformatCalendarPage()`, nous définissons le format de texte du premier vendredi du mois et du 1er mai de l’année en cours. Les formats de texte effectivement utilisés dépendent des cases cochées et des formats définis pour les jours de semaine et les week-ends.
QCalendarWidget setDateTextFormat() nous permet de définir le format de texte de dates individuelles. Nous avons choisi de définir les formats de date lorsque la page du calendrier change (c'est-à-dire lorsqu'un nouveau mois s'affiche) et lorsque le format « jour de la semaine/week-end » est modifié. Nous vérifions quelles cases parmi et sont cochées (le cas échéant) et définissons les formats de texte en conséquence. mayFirstCheckBox firstDayCheckBox
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.