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. QPropertyAnimation for widgets in layout - problem
Forum Updated to NodeBB v4.3 + New Features

QPropertyAnimation for widgets in layout - problem

Scheduled Pinned Locked Moved Solved General and Desktop
2 Posts 1 Posters 1.7k 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.
  • M Offline
    M Offline
    Marek
    wrote on last edited by
    #1

    Hi all,

    I wanted to make widgets increase in height with QPropertyAnimation, when widgets are arranged with QVboxLayout.
    I fought that I solved this problem, but when I animate more than one widget, they start to move/shake during animation.

    I have prepared minimum working example, here example
    The problem appears when you press "open" button for first, second, then third widget, you can see then that they are shaking, moving slightly up and down during "open" animation.

    Has someone idea what to do to avoid this ?
    I can set setSizeConstraint(QLayout::SetFixedSize) on main layout and they dont shake, but then resizing and other doesn't work.

    Best Regards
    Marek

    1 Reply Last reply
    0
    • M Offline
      M Offline
      Marek
      wrote on last edited by
      #2

      Hi

      I have made it to work - with a little help ;)
      so in case anyone had this problem below is single file example (main.cpp)

      #include <QApplication>
      #include <QtWidgets>
      
      class AnimLayout : public QLayout
      {
          Q_OBJECT
      
          Q_PROPERTY(QRect widgetRect
                     READ widgetRect
                     WRITE setWidgetRect
                     NOTIFY widgetRectChanged)
      
      public:
          explicit AnimLayout(QWidget *parent = 0);
          ~AnimLayout();
      
          QSize sizeHint() const;
          void setGeometry(const QRect &);
          QSize minimumSize() const;
          int count() const;
      
          QRect widgetRect() const;
          void setWidgetRect(const QRect &value);
      
          void updateItemPosition();
      private:
          void addItem(QLayoutItem *item);
          QLayoutItem *itemAt(int index) const;
          QLayoutItem *takeAt(int index);
      
      signals:
          void widgetRectChanged(const QRect &value);
      
      public slots:
      private:
          QLayoutItem *item;
          QPropertyAnimation *animation;
      };
      
      struct FrameDataStruct {
          QFrame      *mainFrame;
          QFrame      *upFrame;
          QFrame      *downFrame;
          QPushButton *button;
          QVBoxLayout *upFrameLayout;
          QLabel      *text;
          QVBoxLayout *downFrameLayout;
          QVBoxLayout *frameLayout;
          QPropertyAnimation  *animation;
          int         frame_id;
          int         basic_height;
          bool        expanded;
          AnimLayout  *animLayout;
      };
      
      class Proptest : public QMainWindow
      {
          Q_OBJECT
      
      public:
          explicit Proptest();
          ~Proptest();
      private slots:
          void setDataStruct();
          void startAnimation(int frame_id);
          void animFinished(int frame_id);
      private:
          QMap<int,FrameDataStruct*> frameMap;
          QSignalMapper   *animStartMapper;
          QSignalMapper   *animFinishedMapper;
          bool            initialized;
          QWidget         *scrollWidget;
          QVBoxLayout     *main_layout;
          QWidget         *widget;
          QScrollArea     *scrollArea;
          QVBoxLayout     *central_layout;
          bool            layoutAnimated;
      };
      
      Proptest::Proptest()
          : widget(new QWidget)
      {
          setCentralWidget(widget);
          this->setGeometry(200,200,300,600);
          central_layout=new QVBoxLayout(widget);
          scrollArea=new QScrollArea(widget);
          central_layout->addWidget(scrollArea);
      
      
          animStartMapper=new QSignalMapper(this);
          connect(animStartMapper,SIGNAL(mapped(int)),this,SLOT(startAnimation(int)));
      
          animFinishedMapper=new QSignalMapper(this);
          connect(animFinishedMapper,SIGNAL(mapped(int)),this,SLOT(animFinished(int)));
      
          scrollWidget=new QWidget(widget);
          scrollArea->setWidget(scrollWidget);
          main_layout=new QVBoxLayout(scrollWidget);
          main_layout->setSizeConstraint(QLayout::SetMinAndMaxSize);
          scrollArea->setWidgetResizable(true);
          scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
      
          layoutAnimated=true;
      
          this->setDataStruct();
      }
      void Proptest::setDataStruct() {
          for(int i=0;i<5;i++) {
              FrameDataStruct *r=new FrameDataStruct;
              r->expanded=false;
              r->frame_id=i;
              r->mainFrame=new QFrame(scrollWidget);
              r->upFrame=new QFrame(r->mainFrame);
              r->upFrame->setMinimumHeight(40);
              r->button=new QPushButton(QString("open"),r->upFrame);
              r->upFrameLayout=new QVBoxLayout(r->upFrame);
              r->upFrameLayout->addWidget(r->button);
              r->downFrame=new QFrame(r->mainFrame);
              r->text=new QLabel(QString("some text SOME TEXT some text"),r->downFrame);
              r->downFrameLayout=new QVBoxLayout(r->downFrame);
              r->downFrameLayout->addWidget(r->text);
              r->frameLayout=new QVBoxLayout(r->mainFrame);
              r->frameLayout->addWidget(r->upFrame);
              r->frameLayout->addItem(new QSpacerItem(10,10));
              r->frameLayout->addWidget(r->downFrame);
              r->frameLayout->setStretch(0,0);
              r->frameLayout->setStretch(1,1);
              r->frameLayout->setStretch(2,0);
      
              r->downFrame->setVisible(false);
      
              r->animation=new QPropertyAnimation(r->mainFrame,"minimumHeight");
              r->animation->setDuration(500);
              connect(r->button,SIGNAL(clicked(bool)),animStartMapper,SLOT(map()));
              animStartMapper->setMapping(r->button,r->frame_id);
              connect(r->animation,SIGNAL(finished()),animFinishedMapper,SLOT(map()));
              animFinishedMapper->setMapping(r->animation,r->frame_id);
      
      
              if(layoutAnimated) {
                  r->animLayout=new AnimLayout();
                  r->animLayout->addWidget(r->mainFrame);
                  main_layout->addItem(r->animLayout);
              }
              else {
                  main_layout->addWidget(r->mainFrame);
              }
      
              frameMap.insert(r->frame_id,r);
          }
          main_layout->addItem(new QSpacerItem(10,10,QSizePolicy::Minimum,QSizePolicy::Expanding));
          main_layout->setStretch(main_layout->count()-1,1);
      }
      void Proptest::startAnimation(int frame_id) {
          FrameDataStruct *r=frameMap[frame_id];
          if(r->expanded) {
              r->expanded=false;
              if(layoutAnimated) {
                  r->downFrame->hide();
              }
              else {
                  r->downFrame->setVisible(false);
                  r->animation->setStartValue(r->mainFrame->geometry().height());
                  r->animation->setEndValue(r->basic_height);
              }
      
          } else {
              r->expanded=true;
              if(layoutAnimated) {
                  r->downFrame->show();
              }
              else {
                  r->basic_height=r->mainFrame->geometry().height();
                  r->animation->setStartValue(r->basic_height);
                  r->animation->setEndValue(r->basic_height*2);
                  r->upFrame->setMinimumHeight(r->upFrame->height());
              }
          }
          if(!layoutAnimated)
              r->animation->start();
      }
      void Proptest::animFinished(int frame_id) {
          FrameDataStruct *r=frameMap[frame_id];
          if(r->expanded)
              r->downFrame->setVisible(true);
      }
      Proptest::~Proptest() {
      
      }
      
      AnimLayout::AnimLayout(QWidget *parent) :
          QLayout(parent) ,
          item(0)
      {
          animation = new QPropertyAnimation(this);
          animation->setPropertyName("widgetRect");
          animation->setDuration(400);
          animation->setTargetObject(this);
      }
      
      AnimLayout::~AnimLayout()
      {
          delete item;
      }
      void AnimLayout::addItem(QLayoutItem *newItem)
      {
          Q_ASSERT(!item);
          animation->stop();
          item =newItem;
          emit widgetRectChanged(item->geometry());
          invalidate();
      }
      
      QSize AnimLayout::sizeHint() const
      {
          if (!item)
              return QSize();
          QSize result(item->sizeHint());
      
          int m = 2*margin();
          result += QSize(m,m);
      
          return result;
      }
      
      void AnimLayout::updateItemPosition()
      {
          QRect dest = contentsRect();
      
          animation->setEndValue(dest);
          if (widgetRect()!=dest) {
              animation->start();
          }
      }
      
      void AnimLayout::setGeometry(const QRect &rect)
      {
          QLayout::setGeometry(rect);
      
          updateItemPosition();
      }
      
      QLayoutItem *AnimLayout::itemAt(int i) const
      {
          return i==0?item:0;
      }
      
      QLayoutItem *AnimLayout::takeAt(int i)
      {
          Q_ASSERT(i==0);
          QLayoutItem *r = item;
          item = 0;
          return r;
      }
      
      QRect AnimLayout::widgetRect() const
      {
          if (item)
              return item->geometry();
          return QRect();
      }
      
      void AnimLayout::setWidgetRect(const QRect &value)
      {
          if (item && item->geometry()!=value) {
              item->setGeometry(value);
              emit widgetRectChanged(item->geometry());
          }
      }
      
      QSize AnimLayout::minimumSize() const
      {
          QSize result(item->minimumSize());
      
          int m = 2*margin();
          result += QSize(m,m);
          return result;
      }
      
      int AnimLayout::count() const
      {
          return item?1:0;
      }
      
      int main(int argc, char *argv[])
      {
      
          QApplication a(argc, argv);
      
          Proptest w;
          w.show();
      
          return a.exec();
      }
      
      #include "main.moc"
      
      

      Best Regards
      Marek

      1 Reply Last reply
      1

      • Login

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