Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to make a QLayout ignore the space of a widget that has 0 height?
Forum Updated to NodeBB v4.3 + New Features

How to make a QLayout ignore the space of a widget that has 0 height?

Scheduled Pinned Locked Moved Solved General and Desktop
5 Posts 3 Posters 534 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Y Offline
    Y Offline
    Ylvy
    wrote on last edited by Ylvy
    #1

    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

    del_9EFpl8CzJk.gif

    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());
    }
    
    Christian EhrlicherC JoeCFDJ 2 Replies Last reply
    0
    • Y Ylvy

      @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 widget

      The '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?

      JoeCFDJ Offline
      JoeCFDJ Offline
      JoeCFD
      wrote on last edited by JoeCFD
      #5

      @Ylvy there are default top and bottom margins in the layout as well. Set them to 0.

      1 Reply Last reply
      0
      • Y Ylvy

        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

        del_9EFpl8CzJk.gif

        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());
        }
        
        Christian EhrlicherC Offline
        Christian EhrlicherC Offline
        Christian Ehrlicher
        Lifetime Qt Champion
        wrote on last edited by
        #2

        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

        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
        Visit the Qt Academy at https://academy.qt.io/catalog

        Y 1 Reply Last reply
        1
        • Y Ylvy

          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

          del_9EFpl8CzJk.gif

          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());
          }
          
          JoeCFDJ Offline
          JoeCFDJ Offline
          JoeCFD
          wrote on last edited by JoeCFD
          #3

          @Ylvy https://doc.qt.io/qt-6/stylesheet-customizing.html
          maybe try to use padding? try it out with 0 vertical spacing and 0 vertical margin in the layout.

          1 Reply Last reply
          0
          • Christian EhrlicherC Christian Ehrlicher

            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

            Y Offline
            Y Offline
            Ylvy
            wrote on last edited by Ylvy
            #4

            @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 widget

            The '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?

            JoeCFDJ 1 Reply Last reply
            0
            • Y Ylvy

              @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 widget

              The '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?

              JoeCFDJ Offline
              JoeCFDJ Offline
              JoeCFD
              wrote on last edited by JoeCFD
              #5

              @Ylvy there are default top and bottom margins in the layout as well. Set them to 0.

              1 Reply Last reply
              0
              • Y Ylvy has marked this topic as solved on

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved