How to make a QLayout ignore the space of a widget that has 0 height?
-
I'm trying to create some kind of dropdown/expand animation, in my sample below, whenever the animation ends the widget has its
height
set to 0.The problem is the layout keeps saving some kind of space for each widget with has its height set to 0
How I could make the layout "ignore" this space when the widget has its height 0?
I also tried hiding the widget but it causes some kind of flicker in the "animation"
It makes the animation weird because there's a small delay and some kind of 'jump' from positions, probably the layout is hiding/removing the mentioned 'space'.QMap<QWidget*, QParallelAnimationGroup*> animationMap; void MainWindow::dropDownAnimation(QWidget* widget, bool show, int duration) { QVariantAnimation* heightAnimation = new QVariantAnimation; QGraphicsOpacityEffect* opEff = new QGraphicsOpacityEffect(); QPropertyAnimation* opacityAnimation = new QPropertyAnimation(opEff, "opacity"); if (show) { auto startHeight = widget->height(); auto endHeight = widget->sizeHint().height(); heightAnimation->setStartValue(startHeight); heightAnimation->setEndValue(endHeight); opEff->setOpacity(0); opacityAnimation->setStartValue(0); opacityAnimation->setEndValue(1); if (widget->isHidden()) widget->show(); } else { heightAnimation->setStartValue(widget->height()); heightAnimation->setEndValue(0); opEff->setOpacity(1); opacityAnimation->setStartValue(1); opacityAnimation->setEndValue(0); } widget->setGraphicsEffect(opEff); QEasingCurve curve = QEasingCurve::Type::OutCubic; opacityAnimation->setEasingCurve(curve); opacityAnimation->setDuration(duration); heightAnimation->setEasingCurve(curve); heightAnimation->setDuration(duration); QParallelAnimationGroup* animationGroup = new QParallelAnimationGroup(widget); animationGroup->addAnimation(opacityAnimation); animationGroup->addAnimation(heightAnimation); connect(heightAnimation, &QVariantAnimation::valueChanged, widget, [=](const QVariant& value) { widget->setFixedHeight(value.toInt()); }); if (animationMap.contains(widget)) animationMap[widget]->stop(); else animationGroup->start(QAbstractAnimation::DeleteWhenStopped); animationMap[widget] = animationGroup; connect(animationGroup, &QParallelAnimationGroup::destroyed, this, [=] { widget->setGraphicsEffect(nullptr); if (checkbox->isChecked()) widget->hide(); if (animationGroup == animationMap[widget]) animationMap.remove(widget); else animationMap[widget]->start(QAbstractAnimation::DeleteWhenStopped); }); } MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindowClass()) { ui->setupUi(this); QGridLayout* layout = new QGridLayout(ui->centralWidget); checkbox = new QCheckBox("set Hidden", this); layout->addWidget(checkbox, 0, 0, 1, 1); QString styleSheet = "background-color: black; border-radius: 4px; max-height: 32px; min-height: 32px;"; QString styleSheet_2 = styleSheet + "color: white; max-width: 32px;"; for (int i = 0; i < 10; i++) { QGroupBox* groupBox = new QGroupBox(this); groupBox->setStyleSheet("border: 0px; max-height: 32px;"); QHBoxLayout* boxLayout = new QHBoxLayout(groupBox); boxLayout->setContentsMargins(0, 0, 0, 0); QPushButton* button = new QPushButton("...", this); QPushButton* button_2 = new QPushButton("Hide", this); button->setStyleSheet(styleSheet); button_2->setStyleSheet(styleSheet_2); boxLayout->addWidget(button); boxLayout->addWidget(button_2); connect(button_2, &QPushButton::clicked, this, [=] { dropDownAnimation(groupBox, false, 1000); }); layout->addWidget(groupBox); } QSpacerItem* vSpacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding); layout->addItem(vSpacer, layout->rowCount(), 0, 1, layout->columnCount()); }
-
@JoeCFD I tried the padding property but I couldn't figure out how to use it properly in this use case.
@Christian-Ehrlicher said in How to make a QLayout ignore the space of a widget that has 0 height?:
The problem is the layout keeps saving some kind of space for each widget with has its height set to 0
No, wrong oberservation - it's the spacing between the widgets.
-->
Set the spacing to 0 and add the appropiate spacing to your custom widgetThe 'problem' really was the spacing, what way do you mean by appropriate spacing?
I set the layout spacing to 0 and modified the group box height to 42 and added a vertical spacer to it
QGroupBox* groupBox = new QGroupBox(this); groupBox->setStyleSheet("border: 0px; max-height: 42px;"); QSpacerItem* vSpacer = new QSpacerItem(0, 42, QSizePolicy::Fixed, QSizePolicy::Fixed); boxLayout->addItem(vSpacer);
Now it works as desired.
The problem is that it will not be possible for to me use the layout spacing property.Any other ideas on how I could achieve this without modifying the layout spacing?
-
I'm trying to create some kind of dropdown/expand animation, in my sample below, whenever the animation ends the widget has its
height
set to 0.The problem is the layout keeps saving some kind of space for each widget with has its height set to 0
How I could make the layout "ignore" this space when the widget has its height 0?
I also tried hiding the widget but it causes some kind of flicker in the "animation"
It makes the animation weird because there's a small delay and some kind of 'jump' from positions, probably the layout is hiding/removing the mentioned 'space'.QMap<QWidget*, QParallelAnimationGroup*> animationMap; void MainWindow::dropDownAnimation(QWidget* widget, bool show, int duration) { QVariantAnimation* heightAnimation = new QVariantAnimation; QGraphicsOpacityEffect* opEff = new QGraphicsOpacityEffect(); QPropertyAnimation* opacityAnimation = new QPropertyAnimation(opEff, "opacity"); if (show) { auto startHeight = widget->height(); auto endHeight = widget->sizeHint().height(); heightAnimation->setStartValue(startHeight); heightAnimation->setEndValue(endHeight); opEff->setOpacity(0); opacityAnimation->setStartValue(0); opacityAnimation->setEndValue(1); if (widget->isHidden()) widget->show(); } else { heightAnimation->setStartValue(widget->height()); heightAnimation->setEndValue(0); opEff->setOpacity(1); opacityAnimation->setStartValue(1); opacityAnimation->setEndValue(0); } widget->setGraphicsEffect(opEff); QEasingCurve curve = QEasingCurve::Type::OutCubic; opacityAnimation->setEasingCurve(curve); opacityAnimation->setDuration(duration); heightAnimation->setEasingCurve(curve); heightAnimation->setDuration(duration); QParallelAnimationGroup* animationGroup = new QParallelAnimationGroup(widget); animationGroup->addAnimation(opacityAnimation); animationGroup->addAnimation(heightAnimation); connect(heightAnimation, &QVariantAnimation::valueChanged, widget, [=](const QVariant& value) { widget->setFixedHeight(value.toInt()); }); if (animationMap.contains(widget)) animationMap[widget]->stop(); else animationGroup->start(QAbstractAnimation::DeleteWhenStopped); animationMap[widget] = animationGroup; connect(animationGroup, &QParallelAnimationGroup::destroyed, this, [=] { widget->setGraphicsEffect(nullptr); if (checkbox->isChecked()) widget->hide(); if (animationGroup == animationMap[widget]) animationMap.remove(widget); else animationMap[widget]->start(QAbstractAnimation::DeleteWhenStopped); }); } MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindowClass()) { ui->setupUi(this); QGridLayout* layout = new QGridLayout(ui->centralWidget); checkbox = new QCheckBox("set Hidden", this); layout->addWidget(checkbox, 0, 0, 1, 1); QString styleSheet = "background-color: black; border-radius: 4px; max-height: 32px; min-height: 32px;"; QString styleSheet_2 = styleSheet + "color: white; max-width: 32px;"; for (int i = 0; i < 10; i++) { QGroupBox* groupBox = new QGroupBox(this); groupBox->setStyleSheet("border: 0px; max-height: 32px;"); QHBoxLayout* boxLayout = new QHBoxLayout(groupBox); boxLayout->setContentsMargins(0, 0, 0, 0); QPushButton* button = new QPushButton("...", this); QPushButton* button_2 = new QPushButton("Hide", this); button->setStyleSheet(styleSheet); button_2->setStyleSheet(styleSheet_2); boxLayout->addWidget(button); boxLayout->addWidget(button_2); connect(button_2, &QPushButton::clicked, this, [=] { dropDownAnimation(groupBox, false, 1000); }); layout->addWidget(groupBox); } QSpacerItem* vSpacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding); layout->addItem(vSpacer, layout->rowCount(), 0, 1, layout->columnCount()); }
The problem is the layout keeps saving some kind of space for each widget with has its height set to 0
No, wrong oberservation - it's the spacing between the widgets.
-->
Set the spacing to 0 and add the appropiate spacing to your custom widget -
I'm trying to create some kind of dropdown/expand animation, in my sample below, whenever the animation ends the widget has its
height
set to 0.The problem is the layout keeps saving some kind of space for each widget with has its height set to 0
How I could make the layout "ignore" this space when the widget has its height 0?
I also tried hiding the widget but it causes some kind of flicker in the "animation"
It makes the animation weird because there's a small delay and some kind of 'jump' from positions, probably the layout is hiding/removing the mentioned 'space'.QMap<QWidget*, QParallelAnimationGroup*> animationMap; void MainWindow::dropDownAnimation(QWidget* widget, bool show, int duration) { QVariantAnimation* heightAnimation = new QVariantAnimation; QGraphicsOpacityEffect* opEff = new QGraphicsOpacityEffect(); QPropertyAnimation* opacityAnimation = new QPropertyAnimation(opEff, "opacity"); if (show) { auto startHeight = widget->height(); auto endHeight = widget->sizeHint().height(); heightAnimation->setStartValue(startHeight); heightAnimation->setEndValue(endHeight); opEff->setOpacity(0); opacityAnimation->setStartValue(0); opacityAnimation->setEndValue(1); if (widget->isHidden()) widget->show(); } else { heightAnimation->setStartValue(widget->height()); heightAnimation->setEndValue(0); opEff->setOpacity(1); opacityAnimation->setStartValue(1); opacityAnimation->setEndValue(0); } widget->setGraphicsEffect(opEff); QEasingCurve curve = QEasingCurve::Type::OutCubic; opacityAnimation->setEasingCurve(curve); opacityAnimation->setDuration(duration); heightAnimation->setEasingCurve(curve); heightAnimation->setDuration(duration); QParallelAnimationGroup* animationGroup = new QParallelAnimationGroup(widget); animationGroup->addAnimation(opacityAnimation); animationGroup->addAnimation(heightAnimation); connect(heightAnimation, &QVariantAnimation::valueChanged, widget, [=](const QVariant& value) { widget->setFixedHeight(value.toInt()); }); if (animationMap.contains(widget)) animationMap[widget]->stop(); else animationGroup->start(QAbstractAnimation::DeleteWhenStopped); animationMap[widget] = animationGroup; connect(animationGroup, &QParallelAnimationGroup::destroyed, this, [=] { widget->setGraphicsEffect(nullptr); if (checkbox->isChecked()) widget->hide(); if (animationGroup == animationMap[widget]) animationMap.remove(widget); else animationMap[widget]->start(QAbstractAnimation::DeleteWhenStopped); }); } MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindowClass()) { ui->setupUi(this); QGridLayout* layout = new QGridLayout(ui->centralWidget); checkbox = new QCheckBox("set Hidden", this); layout->addWidget(checkbox, 0, 0, 1, 1); QString styleSheet = "background-color: black; border-radius: 4px; max-height: 32px; min-height: 32px;"; QString styleSheet_2 = styleSheet + "color: white; max-width: 32px;"; for (int i = 0; i < 10; i++) { QGroupBox* groupBox = new QGroupBox(this); groupBox->setStyleSheet("border: 0px; max-height: 32px;"); QHBoxLayout* boxLayout = new QHBoxLayout(groupBox); boxLayout->setContentsMargins(0, 0, 0, 0); QPushButton* button = new QPushButton("...", this); QPushButton* button_2 = new QPushButton("Hide", this); button->setStyleSheet(styleSheet); button_2->setStyleSheet(styleSheet_2); boxLayout->addWidget(button); boxLayout->addWidget(button_2); connect(button_2, &QPushButton::clicked, this, [=] { dropDownAnimation(groupBox, false, 1000); }); layout->addWidget(groupBox); } QSpacerItem* vSpacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding); layout->addItem(vSpacer, layout->rowCount(), 0, 1, layout->columnCount()); }
-
The problem is the layout keeps saving some kind of space for each widget with has its height set to 0
No, wrong oberservation - it's the spacing between the widgets.
-->
Set the spacing to 0 and add the appropiate spacing to your custom widget@JoeCFD I tried the padding property but I couldn't figure out how to use it properly in this use case.
@Christian-Ehrlicher said in How to make a QLayout ignore the space of a widget that has 0 height?:
The problem is the layout keeps saving some kind of space for each widget with has its height set to 0
No, wrong oberservation - it's the spacing between the widgets.
-->
Set the spacing to 0 and add the appropiate spacing to your custom widgetThe 'problem' really was the spacing, what way do you mean by appropriate spacing?
I set the layout spacing to 0 and modified the group box height to 42 and added a vertical spacer to it
QGroupBox* groupBox = new QGroupBox(this); groupBox->setStyleSheet("border: 0px; max-height: 42px;"); QSpacerItem* vSpacer = new QSpacerItem(0, 42, QSizePolicy::Fixed, QSizePolicy::Fixed); boxLayout->addItem(vSpacer);
Now it works as desired.
The problem is that it will not be possible for to me use the layout spacing property.Any other ideas on how I could achieve this without modifying the layout spacing?
-
@JoeCFD I tried the padding property but I couldn't figure out how to use it properly in this use case.
@Christian-Ehrlicher said in How to make a QLayout ignore the space of a widget that has 0 height?:
The problem is the layout keeps saving some kind of space for each widget with has its height set to 0
No, wrong oberservation - it's the spacing between the widgets.
-->
Set the spacing to 0 and add the appropiate spacing to your custom widgetThe 'problem' really was the spacing, what way do you mean by appropriate spacing?
I set the layout spacing to 0 and modified the group box height to 42 and added a vertical spacer to it
QGroupBox* groupBox = new QGroupBox(this); groupBox->setStyleSheet("border: 0px; max-height: 42px;"); QSpacerItem* vSpacer = new QSpacerItem(0, 42, QSizePolicy::Fixed, QSizePolicy::Fixed); boxLayout->addItem(vSpacer);
Now it works as desired.
The problem is that it will not be possible for to me use the layout spacing property.Any other ideas on how I could achieve this without modifying the layout spacing?
-