diff options
author | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2023-12-18 16:39:34 +0100 |
---|---|---|
committer | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2023-12-19 06:06:14 +0100 |
commit | f3fb89ba298e1741320d8bfac9cbd0d503373bff (patch) | |
tree | 86d73060497357f6edea58ebcb26a8b74919f4dc /examples/widgets | |
parent | 4a19e97f70994bc8bb67e26533d18266b8a615bc (diff) |
Update Sliders example
Simplify the "responsive layout" implementation. Just use a QBoxLayout
with changing direction instead of repopulating a QGridLayout, and
change the orientation of one set of sliders instead of creating two
sets in a stacked layout.
Simplify the resizeEvent() implementation accordingly.
Update the documentation snippet text to match the code, and document
the resizeEvent() override.
Pick-to: 6.7 6.6
Fixes: QTBUG-119977
Change-Id: I73a1bb215c956fa283291ebf0ea45ff9a975c727
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
Diffstat (limited to 'examples/widgets')
-rw-r--r-- | examples/widgets/doc/src/sliders.qdoc | 88 | ||||
-rw-r--r-- | examples/widgets/widgets/sliders/slidersgroup.cpp | 34 | ||||
-rw-r--r-- | examples/widgets/widgets/sliders/slidersgroup.h | 6 | ||||
-rw-r--r-- | examples/widgets/widgets/sliders/window.cpp | 97 | ||||
-rw-r--r-- | examples/widgets/widgets/sliders/window.h | 8 |
5 files changed, 97 insertions, 136 deletions
diff --git a/examples/widgets/doc/src/sliders.qdoc b/examples/widgets/doc/src/sliders.qdoc index 871adf0049..9bfb4abdc4 100644 --- a/examples/widgets/doc/src/sliders.qdoc +++ b/examples/widgets/doc/src/sliders.qdoc @@ -18,7 +18,8 @@ manipulated through their properties. The example also demonstrates how signals and slots can be used to - synchronize the behavior of two or more widgets. + synchronize the behavior of two or more widgets, and how to override + \l{QWidget::}{resizeEvent()} to implement a responsive layout. \borderedimage sliders-example.png \caption Screenshot of the Sliders example @@ -31,10 +32,8 @@ QScrollBar and a QDial. \li \c Window is the main widget combining a QGroupBox and a - QStackedWidget. In this example, the QStackedWidget provides a - stack of two \c SlidersGroup widgets. The QGroupBox contain - several widgets that control the behavior of the slider-like - widgets. + SlidersGroup. The QGroupBox contains several widgets that control + the behavior of the slider-like widgets. \endlist @@ -56,28 +55,14 @@ \snippet widgets/sliders/window.cpp 0 - In the constructor we first create the two \c SlidersGroup - widgets that display the slider widgets horizontally and - vertically, and add them to the QStackedWidget. QStackedWidget - provides a stack of widgets where only the top widget is visible. - With \c createControls() we create a connection from a - controlling widget to the QStackedWidget, making the user able to - choose between horizontal and vertical orientation of the slider - widgets. The rest of the controlling mechanisms is implemented by - the same function call. + In the constructor we first create the \c SlidersGroup widget + that displays the slider widgets. With \c createControls() we + create the controlling widgets, and connect those to to the + sliders. \snippet widgets/sliders/window.cpp 1 - \snippet widgets/sliders/window.cpp 2 - - Then we connect the \c horizontalSliders, \c verticalSliders and - \c valueSpinBox to each other, so that the slider widgets and the - control widget will behave synchronized when the current value of - one of them changes. The \c valueChanged() signal is emitted with - the new value as argument. The \c setValue() slot sets the - current value of the widget to the new value, and emits \c - valueChanged() if the new value is different from the old one. - We put the group of control widgets and the stacked widget in a + We put the groups of control widgets and the sliders in a horizontal layout before we initialize the minimum, maximum and current values. The initialization of the current value will propagate to the slider widgets through the connection we made @@ -85,15 +70,14 @@ minimum and maximum values propagate through the connections we created with \c createControls(). + \snippet widgets/sliders/window.cpp 2 \snippet widgets/sliders/window.cpp 3 - \snippet widgets/sliders/window.cpp 4 In the private \c createControls() function, we let a QGroupBox (\c controlsGroup) display the control widgets. A group box can provide a frame, a title and a keyboard shortcut, and displays various other widgets inside itself. The group of control widgets - is composed by two checkboxes, three spin boxes (with labels) and - one combobox. + is composed by two checkboxes, and three spin boxes with labels. After creating the labels, we create the two checkboxes. Checkboxes are typically used to represent features in an @@ -131,8 +115,8 @@ bindings are inverted by default: \uicontrol PageDown increases the current value, and \uicontrol PageUp decreases it. + \snippet widgets/sliders/window.cpp 4 \snippet widgets/sliders/window.cpp 5 - \snippet widgets/sliders/window.cpp 6 Then we create the spin boxes. QSpinBox allows the user to choose a value by clicking the up and down buttons or pressing the \uicontrol @@ -141,14 +125,15 @@ manually. The spin boxes control the minimum, maximum and current values for the QSlider, QScrollBar, and QDial widgets. - We create a QComboBox that allows the user to choose the - orientation of the slider widgets. The QComboBox widget is a - combined button and popup list. It provides a means of presenting - a list of options to the user in a way that takes up the minimum - amount of screen space. + \snippet widgets/sliders/window.cpp 6 - \snippet widgets/sliders/window.cpp 7 - \snippet widgets/sliders/window.cpp 8 + Then we connect the \c slidersGroup and the \c valueSpinBox to each + other, so that the slider widgets and the control widget will behave + synchronized when the current value of one of them changes. + The \c valueChanged() signal is emitted with the new value as + argument. The \c setValue() slot sets the current value of the + widget to the new value, and emits \c valueChanged() if the new + value is different from the old one. We synchronize the behavior of the control widgets and the slider widgets through their signals and slots. We connect each control @@ -158,6 +143,17 @@ lay out the control widgets in a QGridLayout within the \c controlsGroup group box. + \snippet widgets/sliders/window.cpp 7 + + Lastly, we override resizeEvent() from QWidget. We guard against + dividing by zero, and otherwise compute the aspect ratio of the + widget. If the window has a portrait format, then we set the + layout to organize the groups of control widgets and sliders + vertically, and we give the sliders a horizontal orientation. + If the window has a landscape format, then we change the layout + to show the sliders and controlling widgets side by side, and + give the sliders a vertical orientation. + \section1 SlidersGroup Class Definition \snippet widgets/sliders/slidersgroup.h 0 @@ -170,7 +166,8 @@ slot with equivalent functionality to the ones in QAbstractSlider and QSpinBox. In addition, we implement several other public slots to set the minimum and maximum value, and invert the slider - widgets' appearance as well as key bindings. + widgets' appearance as well as key bindings, and set the + orientation. \section1 SlidersGroup Class Implementation @@ -183,24 +180,21 @@ focus. The Qt::StrongFocus policy means that the widget accepts focus by both tabbing and clicking. + \snippet widgets/sliders/slidersgroup.cpp 1 + Then we connect the widgets with each other, so that they will stay synchronized when the current value of one of them changes. - \snippet widgets/sliders/slidersgroup.cpp 1 - \snippet widgets/sliders/slidersgroup.cpp 2 - We connect \c {dial}'s \c valueChanged() signal to the \c{SlidersGroup}'s \c valueChanged() signal, to notify the other widgets in the application (i.e., the control widgets) of the changed value. - \snippet widgets/sliders/slidersgroup.cpp 3 \codeline \snippet widgets/sliders/slidersgroup.cpp 4 - Finally, depending on the \l {Qt::Orientation}{orientation} given - at the time of construction, we choose and create the layout for - the slider widgets within the group box. + Finally, we create the layout for the slider widgets within the + group box. We start with a horizontal arrangement of the sliders. \snippet widgets/sliders/slidersgroup.cpp 5 \snippet widgets/sliders/slidersgroup.cpp 6 @@ -233,4 +227,12 @@ \l{QAbstractSlider::invertedAppearance}{invertedAppearance} and \l{QAbstractSlider::invertedControls}{invertedControls} properties. + + \snippet widgets/sliders/slidersgroup.cpp 15 + + The setOrientation() slot controls the direction of the layout + and the orientation of the sliders. In a horizontal group, the + sliders have a horizontal orientation, and are laid out on top + of each other. In a vertical group, the sliders have a vertical + orientation, and are laid out next to each other. */ diff --git a/examples/widgets/widgets/sliders/slidersgroup.cpp b/examples/widgets/widgets/sliders/slidersgroup.cpp index c5d01cdb37..87841c43f9 100644 --- a/examples/widgets/widgets/sliders/slidersgroup.cpp +++ b/examples/widgets/widgets/sliders/slidersgroup.cpp @@ -9,39 +9,28 @@ #include <QSlider> //! [0] -SlidersGroup::SlidersGroup(Qt::Orientation orientation, const QString &title, - QWidget *parent) +SlidersGroup::SlidersGroup(const QString &title, QWidget *parent) : QGroupBox(title, parent) { - slider = new QSlider(orientation); + slider = new QSlider; slider->setFocusPolicy(Qt::StrongFocus); slider->setTickPosition(QSlider::TicksBothSides); slider->setTickInterval(10); slider->setSingleStep(1); - scrollBar = new QScrollBar(orientation); + scrollBar = new QScrollBar; scrollBar->setFocusPolicy(Qt::StrongFocus); dial = new QDial; dial->setFocusPolicy(Qt::StrongFocus); +//! [0] //! [1] connect(slider, &QSlider::valueChanged, scrollBar, &QScrollBar::setValue); connect(scrollBar, &QScrollBar::valueChanged, dial, &QDial::setValue); connect(dial, &QDial::valueChanged, slider, &QSlider::setValue); -//! [0] //! [1] connect(dial, &QDial::valueChanged, this, &SlidersGroup::valueChanged); -//! [1] //! [2] - -//! [2] //! [3] - QBoxLayout::Direction direction; -//! [3] //! [4] - - if (orientation == Qt::Horizontal) - direction = QBoxLayout::TopToBottom; - else - direction = QBoxLayout::LeftToRight; - - QBoxLayout *slidersLayout = new QBoxLayout(direction); +//! [1] //! [4] + slidersLayout = new QBoxLayout(QBoxLayout::LeftToRight); slidersLayout->addWidget(slider); slidersLayout->addWidget(scrollBar); slidersLayout->addWidget(dial); @@ -96,3 +85,14 @@ void SlidersGroup::invertKeyBindings(bool invert) dial->setInvertedControls(invert); } //! [14] + +//! [15] +void SlidersGroup::setOrientation(Qt::Orientation orientation) +{ + slidersLayout->setDirection(orientation == Qt::Horizontal + ? QBoxLayout::TopToBottom + : QBoxLayout::LeftToRight); + scrollBar->setOrientation(orientation); + slider->setOrientation(orientation); +} +//! [15] diff --git a/examples/widgets/widgets/sliders/slidersgroup.h b/examples/widgets/widgets/sliders/slidersgroup.h index 66821ca558..7e7d887018 100644 --- a/examples/widgets/widgets/sliders/slidersgroup.h +++ b/examples/widgets/widgets/sliders/slidersgroup.h @@ -10,6 +10,7 @@ QT_BEGIN_NAMESPACE class QDial; class QScrollBar; class QSlider; +class QBoxLayout; QT_END_NAMESPACE //! [0] @@ -18,8 +19,7 @@ class SlidersGroup : public QGroupBox Q_OBJECT public: - SlidersGroup(Qt::Orientation orientation, const QString &title, - QWidget *parent = nullptr); + SlidersGroup(const QString &title, QWidget *parent = nullptr); signals: void valueChanged(int value); @@ -30,11 +30,13 @@ public slots: void setMaximum(int value); void invertAppearance(bool invert); void invertKeyBindings(bool invert); + void setOrientation(Qt::Orientation orientation); private: QSlider *slider; QScrollBar *scrollBar; QDial *dial; + QBoxLayout *slidersLayout; }; //! [0] diff --git a/examples/widgets/widgets/sliders/window.cpp b/examples/widgets/widgets/sliders/window.cpp index a2c2fe89eb..c62c3b83f5 100644 --- a/examples/widgets/widgets/sliders/window.cpp +++ b/examples/widgets/widgets/sliders/window.cpp @@ -13,29 +13,15 @@ Window::Window(QWidget *parent) : QWidget(parent) { - horizontalSliders = new SlidersGroup(Qt::Horizontal, tr("Horizontal")); - verticalSliders = new SlidersGroup(Qt::Vertical, tr("Vertical")); - - stackedWidget = new QStackedWidget; - stackedWidget->addWidget(horizontalSliders); - stackedWidget->addWidget(verticalSliders); + slidersGroup = new SlidersGroup(tr("Sliders")); createControls(tr("Controls")); //! [0] //! [1] - connect(horizontalSliders, &SlidersGroup::valueChanged, -//! [1] //! [2] - verticalSliders, &SlidersGroup::setValue); - connect(verticalSliders, &SlidersGroup::valueChanged, - valueSpinBox, &QSpinBox::setValue); - connect(valueSpinBox, &QSpinBox::valueChanged, - horizontalSliders, &SlidersGroup::setValue); - - layout = new QGridLayout; - layout->addWidget(stackedWidget, 0, 1); - layout->addWidget(controlsGroup, 0, 0); - + layout = new QBoxLayout(QBoxLayout::LeftToRight); + layout->addWidget(controlsGroup); + layout->addWidget(slidersGroup); setLayout(layout); minimumSpinBox->setValue(0); @@ -44,11 +30,11 @@ Window::Window(QWidget *parent) setWindowTitle(tr("Sliders")); } -//! [2] +//! [1] -//! [3] +//! [2] void Window::createControls(const QString &title) -//! [3] //! [4] +//! [2] //! [3] { controlsGroup = new QGroupBox(title); @@ -59,9 +45,9 @@ void Window::createControls(const QString &title) invertedAppearance = new QCheckBox(tr("Inverted appearance")); invertedKeyBindings = new QCheckBox(tr("Inverted key bindings")); -//! [4] //! [5] +//! [3] //! [4] minimumSpinBox = new QSpinBox; -//! [5] //! [6] +//! [4] //! [5] minimumSpinBox->setRange(-100, 100); minimumSpinBox->setSingleStep(1); @@ -73,30 +59,19 @@ void Window::createControls(const QString &title) valueSpinBox->setRange(-100, 100); valueSpinBox->setSingleStep(1); - orientationCombo = new QComboBox; - orientationCombo->addItem(tr("Horizontal slider-like widgets")); - orientationCombo->addItem(tr("Vertical slider-like widgets")); - -//! [6] //! [7] - connect(orientationCombo, &QComboBox::activated, -//! [7] //! [8] - stackedWidget, &QStackedWidget::setCurrentIndex); - connect(minimumSpinBox, &QSpinBox::valueChanged, - horizontalSliders, &SlidersGroup::setMinimum); +//! [5] //! [6] + connect(slidersGroup, &SlidersGroup::valueChanged, + valueSpinBox, &QSpinBox::setValue); + connect(valueSpinBox, &QSpinBox::valueChanged, + slidersGroup, &SlidersGroup::setValue); connect(minimumSpinBox, &QSpinBox::valueChanged, - verticalSliders, &SlidersGroup::setMinimum); - connect(maximumSpinBox, &QSpinBox::valueChanged, - horizontalSliders, &SlidersGroup::setMaximum); + slidersGroup, &SlidersGroup::setMinimum); connect(maximumSpinBox, &QSpinBox::valueChanged, - verticalSliders, &SlidersGroup::setMaximum); + slidersGroup, &SlidersGroup::setMaximum); connect(invertedAppearance, &QCheckBox::toggled, - horizontalSliders, &SlidersGroup::invertAppearance); - connect(invertedAppearance, &QCheckBox::toggled, - verticalSliders, &SlidersGroup::invertAppearance); - connect(invertedKeyBindings, &QCheckBox::toggled, - horizontalSliders, &SlidersGroup::invertKeyBindings); + slidersGroup, &SlidersGroup::invertAppearance); connect(invertedKeyBindings, &QCheckBox::toggled, - verticalSliders, &SlidersGroup::invertKeyBindings); + slidersGroup, &SlidersGroup::invertKeyBindings); QGridLayout *controlsLayout = new QGridLayout; controlsLayout->addWidget(minimumLabel, 0, 0); @@ -107,40 +82,26 @@ void Window::createControls(const QString &title) controlsLayout->addWidget(valueSpinBox, 2, 1); controlsLayout->addWidget(invertedAppearance, 0, 2); controlsLayout->addWidget(invertedKeyBindings, 1, 2); - controlsLayout->addWidget(orientationCombo, 3, 0, 1, 3); controlsGroup->setLayout(controlsLayout); } -//! [8] +//! [6] -void Window::resizeEvent(QResizeEvent *e) +//! [7] +void Window::resizeEvent(QResizeEvent *) { - Q_UNUSED(e); if (width() == 0 || height() == 0) return; - const double aspectRatio = double(width()) / double(height()); - - if ((aspectRatio < 1.0) && (oldAspectRatio > 1.0)) { - layout->removeWidget(controlsGroup); - layout->removeWidget(stackedWidget); + const double aspectRatio = double(width()) / double(height()); - layout->addWidget(stackedWidget, 1, 0); - layout->addWidget(controlsGroup, 0, 0); - - oldAspectRatio = aspectRatio; - } - else if ((aspectRatio > 1.0) && (oldAspectRatio < 1.0)) { - layout->removeWidget(controlsGroup); - layout->removeWidget(stackedWidget); - - layout->addWidget(stackedWidget, 0, 1); - layout->addWidget(controlsGroup, 0, 0); - - oldAspectRatio = aspectRatio; + if (aspectRatio < 1.0) { + layout->setDirection(QBoxLayout::TopToBottom); + slidersGroup->setOrientation(Qt::Horizontal); + } else if (aspectRatio > 1.0) { + layout->setDirection(QBoxLayout::LeftToRight); + slidersGroup->setOrientation(Qt::Vertical); } } - - - +//! [7] diff --git a/examples/widgets/widgets/sliders/window.h b/examples/widgets/widgets/sliders/window.h index fa627eabd3..8d7338f27c 100644 --- a/examples/widgets/widgets/sliders/window.h +++ b/examples/widgets/widgets/sliders/window.h @@ -29,9 +29,7 @@ private: void createControls(const QString &title); void resizeEvent(QResizeEvent *e); - SlidersGroup *horizontalSliders; - SlidersGroup *verticalSliders; - QStackedWidget *stackedWidget; + SlidersGroup *slidersGroup; QGroupBox *controlsGroup; QLabel *minimumLabel; @@ -42,9 +40,7 @@ private: QSpinBox *minimumSpinBox; QSpinBox *maximumSpinBox; QSpinBox *valueSpinBox; - QComboBox *orientationCombo; - QGridLayout *layout; - double oldAspectRatio; + QBoxLayout *layout; }; //! [0] |