Sur cette page

Exemple de boîtes tournantes

L'exemple de Spin Boxes montre comment utiliser les différents types de spin box disponibles dans Qt, d'un simple widget QSpinBox à des éditeurs plus complexes comme le widget QDateTimeEdit.

Galerie des différents types de boîtes d'essorage

L'exemple se compose d'une seule classe Window qui est utilisée pour afficher les différents widgets basés sur les spin boxes disponibles dans Qt.

Définition de la classe de fenêtre

La classe Window hérite de QWidget et contient deux emplacements utilisés pour fournir des fonctions interactives :

class Window : public QWidget
{
    Q_OBJECT

public:
    Window(QWidget *parent = nullptr);

public slots:
    void changePrecision(int decimals);
    void setFormatString(const QString &formatString);

private:
    void createSpinBoxes();
    void createDateTimeEdits();
    void createDoubleSpinBoxes();

    QDateTimeEdit *meetingEdit;
    QDoubleSpinBox *doubleSpinBox;
    QDoubleSpinBox *priceSpinBox;
    QDoubleSpinBox *scaleSpinBox;
    QGroupBox *spinBoxesGroup;
    QGroupBox *editsGroup;
    QGroupBox *doubleSpinBoxesGroup;
    QLabel *meetingLabel;
    QSpinBox *groupSeparatorSpinBox;
    QDoubleSpinBox *groupSeparatorSpinBox_d;
};

Les fonctions privées sont utilisées pour configurer chaque type de boîte à boutons dans la fenêtre. Nous utilisons des variables membres pour garder une trace des différents widgets afin qu'ils puissent être reconfigurés si nécessaire.

Mise en œuvre de la classe de fenêtre

Le constructeur appelle simplement des fonctions privées pour configurer les différents types de boîtes à boutons utilisés dans l'exemple, et place chaque groupe dans une disposition :

Window::Window(QWidget *parent)
    : QWidget(parent)
{
    createSpinBoxes();
    createDateTimeEdits();
    createDoubleSpinBoxes();

    QHBoxLayout *layout = new QHBoxLayout;
    layout->addWidget(spinBoxesGroup);
    layout->addWidget(editsGroup);
    layout->addWidget(doubleSpinBoxesGroup);
    setLayout(layout);

    setWindowTitle(tr("Spin Boxes"));
}

Nous utilisons la disposition pour gérer l'agencement des widgets enfants de la fenêtre et pour modifier le titre de la fenêtre.

La fonction createSpinBoxes() construit une fenêtre QGroupBox et y place trois widgets QSpinBox avec des étiquettes descriptives pour indiquer les types d'entrée qu'ils attendent.

void Window::createSpinBoxes()
{
    spinBoxesGroup = new QGroupBox(tr("Spinboxes"));

    QLabel *integerLabel = new QLabel(tr("Enter a value between "
        "%1 and %2:").arg(-20).arg(20));
    QSpinBox *integerSpinBox = new QSpinBox;
    integerSpinBox->setRange(-20, 20);
    integerSpinBox->setSingleStep(1);
    integerSpinBox->setValue(0);

La première boîte à boutons montre la manière la plus simple d'utiliser QSpinBox. Elle accepte des valeurs comprises entre -20 et 20, la valeur actuelle peut être augmentée ou diminuée de 1 à l'aide des boutons fléchés ou des touches Up et Down, et la valeur par défaut est 0.

La deuxième boîte de dialogue utilise un pas plus grand et affiche un suffixe pour fournir plus d'informations sur le type de données que le nombre représente :

    QLabel *zoomLabel = new QLabel(tr("Enter a zoom value between "
        "%1 and %2:").arg(0).arg(1000));
    QSpinBox *zoomSpinBox = new QSpinBox;
    zoomSpinBox->setRange(0, 1000);
    zoomSpinBox->setSingleStep(10);
    zoomSpinBox->setSuffix("%");
    zoomSpinBox->setSpecialValueText(tr("Automatic"));
    zoomSpinBox->setValue(100);

Cette boîte de filtrage affiche également un special value au lieu de la valeur minimale définie pour elle. Cela signifie qu'elle n'affichera jamais 0%, mais qu'elle affichera Automatic lorsque la valeur minimale sera sélectionnée.

La troisième boîte à boutons montre comment un préfixe peut être utilisé :

    QLabel *priceLabel = new QLabel(tr("Enter a price between "
        "%1 and %2:").arg(0).arg(999));
    QSpinBox *priceSpinBox = new QSpinBox;
    priceSpinBox->setRange(0, 999);
    priceSpinBox->setSingleStep(1);
    priceSpinBox->setPrefix("$");
    priceSpinBox->setValue(99);

Pour des raisons de simplicité, nous montrons une spin box avec un préfixe et sans suffixe. Il est également possible d'utiliser les deux en même temps.

    groupSeparatorSpinBox = new QSpinBox;
    groupSeparatorSpinBox->setRange(-99999999, 99999999);
    groupSeparatorSpinBox->setValue(1000);
    groupSeparatorSpinBox->setGroupSeparatorShown(true);
    QCheckBox *groupSeparatorChkBox = new QCheckBox;
    groupSeparatorChkBox->setText(tr("Show group separator"));
    groupSeparatorChkBox->setChecked(true);
    connect(groupSeparatorChkBox, &QCheckBox::toggled, groupSeparatorSpinBox,
            &QSpinBox::setGroupSeparatorShown);

    QLabel *hexLabel = new QLabel(tr("Enter a value between "
        "%1 and %2:").arg('-' + QString::number(31, 16)).arg(QString::number(31, 16)));
    QSpinBox *hexSpinBox = new QSpinBox;
    hexSpinBox->setRange(-31, 31);
    hexSpinBox->setSingleStep(1);
    hexSpinBox->setValue(0);
    hexSpinBox->setDisplayIntegerBase(16);

    QVBoxLayout *spinBoxLayout = new QVBoxLayout;
    spinBoxLayout->addWidget(integerLabel);
    spinBoxLayout->addWidget(integerSpinBox);
    spinBoxLayout->addWidget(zoomLabel);
    spinBoxLayout->addWidget(zoomSpinBox);
    spinBoxLayout->addWidget(priceLabel);
    spinBoxLayout->addWidget(priceSpinBox);
    spinBoxLayout->addWidget(hexLabel);
    spinBoxLayout->addWidget(hexSpinBox);
    spinBoxLayout->addWidget(groupSeparatorChkBox);
    spinBoxLayout->addWidget(groupSeparatorSpinBox);
    spinBoxesGroup->setLayout(spinBoxLayout);
}

Le reste de la fonction établit une mise en page pour le cadre et place chacun des widgets à l'intérieur.

La fonction createDateTimeEdits() construit un autre cadre avec une sélection de boîtes à boutons utilisées pour l'édition des dates et des heures.

void Window::createDateTimeEdits()
{
    editsGroup = new QGroupBox(tr("Date and time spin boxes"));

    QLabel *dateLabel = new QLabel;
    QDateEdit *dateEdit = new QDateEdit(QDate::currentDate());
    dateEdit->setDateRange(QDate(2005, 1, 1), QDate(2010, 12, 31));
    dateLabel->setText(tr("Appointment date (between %0 and %1):")
                       .arg(dateEdit->minimumDate().toString(Qt::ISODate))
                       .arg(dateEdit->maximumDate().toString(Qt::ISODate)));

La première boîte tournante est un widget QDateEdit capable d'accepter des dates dans un intervalle donné spécifié à l'aide des valeurs QDate. Les boutons fléchés et les touches Up et Down peuvent être utilisés pour augmenter ou diminuer les valeurs de l'année, du mois et du jour lorsque le curseur se trouve dans la section correspondante.

La deuxième boîte de dialogue est un widget QTimeEdit:

    QLabel *timeLabel = new QLabel;
    QTimeEdit *timeEdit = new QTimeEdit(QTime::currentTime());
    timeEdit->setTimeRange(QTime(9, 0, 0, 0), QTime(16, 30, 0, 0));
    timeLabel->setText(tr("Appointment time (between %0 and %1):")
                       .arg(timeEdit->minimumTime().toString(Qt::ISODate))
                       .arg(timeEdit->maximumTime().toString(Qt::ISODate)));

Les valeurs acceptables pour l'heure sont définies à l'aide des valeurs QTime.

La troisième boîte tournante est un widget QDateTimeEdit qui peut afficher à la fois la date et l'heure, et nous plaçons une étiquette au-dessus pour indiquer la fourchette d'heures autorisées pour une réunion. Ces widgets sont mis à jour lorsque l'utilisateur modifie une chaîne de format.

    meetingLabel = new QLabel;
    meetingEdit = new QDateTimeEdit(QDateTime::currentDateTime());

La chaîne de format utilisée pour l'éditeur de date et d'heure, qui figure également dans la chaîne affichée par l'étiquette, est choisie parmi un ensemble de chaînes dans une boîte combinée :

    QLabel *formatLabel = new QLabel(tr("Format string for the meeting date "
                                        "and time:"));
    QComboBox *formatComboBox = new QComboBox;
    formatComboBox->addItem("yyyy-MM-dd hh:mm:ss (zzz 'ms')");
    formatComboBox->addItem("hh:mm:ss MM/dd/yyyy");
    formatComboBox->addItem("hh:mm:ss dd/MM/yyyy");
    formatComboBox->addItem("hh:mm:ss");
    formatComboBox->addItem("hh:mm ap");

    connect(formatComboBox, &QComboBox::textActivated,
            this, &Window::setFormatString);

Un signal provenant de cette boîte combinée est connecté à un emplacement dans la classe Window (présentée plus loin).

    QVBoxLayout *editsLayout = new QVBoxLayout;
    editsLayout->addWidget(dateLabel);
    editsLayout->addWidget(dateEdit);
    editsLayout->addWidget(timeLabel);
    editsLayout->addWidget(timeEdit);
    editsLayout->addWidget(meetingLabel);
    editsLayout->addWidget(meetingEdit);
    editsLayout->addWidget(formatLabel);
    editsLayout->addWidget(formatComboBox);
    editsGroup->setLayout(editsLayout);
}

Chaque widget enfant de la boîte de groupe est placé dans une disposition.

L'emplacement setFormatString() est appelé chaque fois que l'utilisateur sélectionne une nouvelle chaîne de format dans la boîte combinée. Le format d'affichage du widget QDateTimeEdit est défini à l'aide de la chaîne brute transmise par le signal :

void Window::setFormatString(const QString &formatString)
{
    meetingEdit->setDisplayFormat(formatString);

En fonction des sections visibles dans le widget, nous définissons une nouvelle date ou une nouvelle plage horaire et mettons à jour l'étiquette associée afin de fournir des informations pertinentes à l'utilisateur :

    if (meetingEdit->displayedSections() & QDateTimeEdit::DateSections_Mask) {
        meetingEdit->setDateRange(QDate(2004, 11, 1), QDate(2005, 11, 30));
        meetingLabel->setText(tr("Meeting date (between %0 and %1):")
            .arg(meetingEdit->minimumDate().toString(Qt::ISODate))
            .arg(meetingEdit->maximumDate().toString(Qt::ISODate)));
    } else {
        meetingEdit->setTimeRange(QTime(0, 7, 20, 0), QTime(21, 0, 0, 0));
        meetingLabel->setText(tr("Meeting time (between %0 and %1):")
            .arg(meetingEdit->minimumTime().toString(Qt::ISODate))
            .arg(meetingEdit->maximumTime().toString(Qt::ISODate)));
    }
}

Lorsque la chaîne de format est modifiée, il y aura une étiquette et un widget de saisie appropriés pour les dates, les heures ou les deux types d'entrée.

La fonction createDoubleSpinBoxes() construit trois boîtes de dialogue utilisées pour saisir des nombres à virgule flottante en double précision :

void Window::createDoubleSpinBoxes()
{
    doubleSpinBoxesGroup = new QGroupBox(tr("Double precision spinboxes"));

    QLabel *precisionLabel = new QLabel(tr("Number of decimal places "
                                           "to show:"));
    QSpinBox *precisionSpinBox = new QSpinBox;
    precisionSpinBox->setRange(0, 100);
    precisionSpinBox->setValue(2);

Avant de construire les widgets QDoubleSpinBox, nous créons une boîte à outils pour contrôler le nombre de décimales qu'ils affichent. Par défaut, seules deux décimales sont affichées dans les boîtes à outils suivantes, chacune étant l'équivalent d'une boîte à outils dans le groupe créé par la fonction createSpinBoxes().

La première double boîte à outils montre une boîte à outils de base à double précision avec la même plage, la même taille de pas et la même valeur par défaut que la première boîte à outils de la fonction createSpinBoxes():

    QLabel *doubleLabel = new QLabel(tr("Enter a value between "
        "%1 and %2:").arg(-20).arg(20));
    doubleSpinBox = new QDoubleSpinBox;
    doubleSpinBox->setRange(-20.0, 20.0);
    doubleSpinBox->setSingleStep(1.0);
    doubleSpinBox->setValue(0.0);

Toutefois, cette boîte à outils permet également d'introduire des valeurs non entières.

La deuxième boîte de dialogue affiche un suffixe et une valeur spéciale au lieu de la valeur minimale :

    QLabel *scaleLabel = new QLabel(tr("Enter a scale factor between "
        "%1 and %2:").arg(0).arg(1000.0));
    scaleSpinBox = new QDoubleSpinBox;
    scaleSpinBox->setRange(0.0, 1000.0);
    scaleSpinBox->setSingleStep(10.0);
    scaleSpinBox->setSuffix("%");
    scaleSpinBox->setSpecialValueText(tr("No scaling"));
    scaleSpinBox->setValue(100.0);

La troisième boîte à outils affiche un préfixe au lieu d'un suffixe :

    QLabel *priceLabel = new QLabel(tr("Enter a price between "
        "%1 and %2:").arg(0).arg(1000));
    priceSpinBox = new QDoubleSpinBox;
    priceSpinBox->setRange(0.0, 1000.0);
    priceSpinBox->setSingleStep(1.0);
    priceSpinBox->setPrefix("$");
    priceSpinBox->setValue(99.99);

    connect(precisionSpinBox, &QSpinBox::valueChanged,

Nous connectons le widget QSpinBox qui spécifie la précision à un emplacement dans la classe Window.

    QVBoxLayout *spinBoxLayout = new QVBoxLayout;
    spinBoxLayout->addWidget(precisionLabel);
    spinBoxLayout->addWidget(precisionSpinBox);
    spinBoxLayout->addWidget(doubleLabel);
    spinBoxLayout->addWidget(doubleSpinBox);
    spinBoxLayout->addWidget(scaleLabel);
    spinBoxLayout->addWidget(scaleSpinBox);
    spinBoxLayout->addWidget(priceLabel);
    spinBoxLayout->addWidget(priceSpinBox);
    spinBoxLayout->addWidget(groupSeparatorChkBox);
    spinBoxLayout->addWidget(groupSeparatorSpinBox_d);
    doubleSpinBoxesGroup->setLayout(spinBoxLayout);
}

Le reste de la fonction place chacun des widgets dans une disposition pour le cadre.

Le slot changePrecision() est appelé lorsque l'utilisateur modifie la valeur du champ de précision :

void Window::changePrecision(int decimals)
{
    doubleSpinBox->setDecimals(decimals);
    scaleSpinBox->setDecimals(decimals);
    priceSpinBox->setDecimals(decimals);
}

Cette fonction utilise simplement l'entier fourni par le signal pour spécifier le nombre de décimales dans chacun des widgets QDoubleSpinBox. Chacun d'entre eux sera mis à jour automatiquement lorsque sa propriété decimals sera modifiée.

Exemple de projet @ code.qt.io

© 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.