旋钮盒示例

旋钮盒示例展示了如何在 Qt 中使用各种不同的旋钮盒类型,从简单的 QSpinBox 小部件到更复杂的编辑器,如 QDateTimeEdit 小部件。

本例由一个单一的 Window 类组成,用于显示 Qt 提供的各种基于旋钮盒的小部件。

Window 类定义

Window 类继承自 QWidget 并且包含两个槽,用于提供交互功能

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;
};

私有函数用于在窗口中设置每种类型的旋钮盒。我们使用成员变量来跟踪各种小部件,以便在需要时重新配置它们。

Window 类实现

构造函数简单地调用私有函数来设置示例中使用的不同类型的旋钮盒,并将每个组放置在布局中

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"));
}

我们使用布局来管理窗口子小部件的排列,并更改窗口标题。

函数 createSpinBoxes() 构建一个 QGroupBox,并在其中放置三个带描述性标签的 QSpinBox 小部件,以指示它们所期望的输入类型。

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);

第一个旋钮盒展示了使用 QSpinBox 的最简单方法。它接受从 -20 到 20 的值,当前值可以通过箭头按钮或 向上向下 键增加或减少 1,默认值是 0。

第二个旋钮盒使用更大的步长,并显示后缀以提供关于数字所表示数据类型的更多信息

    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);

此旋钮盒还显示一个 特殊值 而不是为其定义的最小值。这意味着它永远不会显示 0%,当选择最小值时,它会显示 自动

第三个旋钮盒展示了如何使用前缀

    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);

为了简单起见,我们展示了带有前缀但没有后缀的旋钮盒。同时使用两者也是可能的。

    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);
}

函数的其余部分为组框设置布局,并将每个小部件放置在其中。

函数 createDateTimeEdits() 构建另一个包含用于编辑日期和时间的旋钮盒选择的组框。

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)));

第一个旋转框是一个QDateEdit小部件,可以接受使用QDate值指定的范围内的日期。当光标位于相关部分时,可以使用箭头按钮和键和键来增加和减少年、月和日的值。

第二个旋转框是一个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)));

时间的可接受值使用QTime值定义。

第三个旋转框是一个QDateTimeEdit小部件,可以显示日期和时间值,我们在它上面放置一个标签以指示会议允许的时间范围。这些小部件将在用户更改格式字符串时更新。

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

用于日期时间编辑器的格式字符串,也显示在标签显示的字符串中,是从组合框中选择的字符串集中选择的

    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);

从这个组合框发出的信号连接到(将在后面显示的)Window类中的一个槽。

    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);
}

组合框中的每个子小部件都放置在一个布局中。

当用户在组合框中选定一个新的格式字符串时,会调用setFormatString()槽。使用信号传递的原始字符串设置QDateTimeEdit小部件的显示格式

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

根据小部件中可见的部分,我们设置新的日期或时间范围,并更新相关标签以提供有关用户的相关信息

    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)));
    }
}

当格式字符串改变时,将会有相应的日期、时间或两者输入类型的标签和输入小部件。

createDoubleSpinBoxes()函数构建了三个旋转框,用于输入双精度浮点数

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);

在构建QDoubleSpinBox小部件之前,我们创建一个旋转框来控制显示的小数位数。默认情况下,以下旋转框只显示两位小数,每个旋转框都是createSpinBoxes()函数创建的组的等效旋转框。

第一个双精度旋转框显示一个基本的双精度旋转框,具有与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);

但是,这个旋转框也允许输入非整数值。

第二个旋转框显示一个后缀,并显示一个特殊值而不是最小值

    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);

第三个旋转框显示一个前缀而不是后缀

    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,

我们将指定精确度的QSpinBox小部件连接到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);
}

函数的其余部分将每个小部件放入组合框的布局。

当用户在精确度旋转框中更改值时,会调用changePrecision()

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

这个函数只是使用信号提供的整数来指定每个QDoubleSpinBox小部件中的小数位数。只要它们的decimals属性更改,每个都将自动更新。

示例项目 @ code.qt.io

© 2024 The Qt Company Ltd. 所包含的文档贡献是各自所有人的版权。此处提供的文档是根据自由软件基金会发布的GNU自由文档许可协议版本1.3的条款许可的。Qt和相关的标志是The Qt Company Ltd.在芬兰和/或世界各地注册的商标。所有其他商标均为其 respective owner的所有财产。