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 draw and correctly animate progress bar in QTableView?
QtWS25 Last Chance

How to draw and correctly animate progress bar in QTableView?

Scheduled Pinned Locked Moved General and Desktop
qtableviewqprogressbarprogress bar
23 Posts 4 Posters 17.2k 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.
  • H hamov
    16 Jul 2015, 12:17

    @mrjj Thanks for helping.
    Yep, it didn't work even with button. There are no animation after button release(I'm connected button release() with QListView's update()). Only on mouse hover or resize.

    M Offline
    M Offline
    mrjj
    Lifetime Qt Champion
    wrote on 16 Jul 2015, 17:54 last edited by
    #14

    @hamov

    Just to be sure. By animation, you mean that the green part cover more/moves. as when moving the mouse over.

    Since it can draw , (when mouse move/over) it somehow must be the signal that get lost ?

    you did also try direct repaint ?

    void MainWin::on_toolButton_clicked()
    {
    m_table->repaint();
    }

    If that dont work then your Qt install must be funky somehow.

    H 1 Reply Last reply 16 Jul 2015, 22:04
    0
    • M mrjj
      16 Jul 2015, 17:54

      @hamov

      Just to be sure. By animation, you mean that the green part cover more/moves. as when moving the mouse over.

      Since it can draw , (when mouse move/over) it somehow must be the signal that get lost ?

      you did also try direct repaint ?

      void MainWin::on_toolButton_clicked()
      {
      m_table->repaint();
      }

      If that dont work then your Qt install must be funky somehow.

      H Offline
      H Offline
      hamov
      wrote on 16 Jul 2015, 22:04 last edited by hamov
      #15

      @mrjj
      Yes, that's right.
      Here is my code with timer and button:
      *.hpp

      class MainWindow : public QMainWindow
      {
          Q_OBJECT
      
      public:
          MainWindow(QWidget *parent = 0);
      private slots:
          void buttonPressed();
      private:
          void createList();
          void startTimer();
      private:
          QListView* m_list;
          QStandardItemModel* m_model;
          QPushButton* m_button;
          QTimer* m_timer;
      };
      

      *.cpp

      class TestDelegate : public QStyledItemDelegate
      {
      public:
          TestDelegate(QObject* parent = 0);
      
      public:
          virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
      };
      
      TestDelegate::
      TestDelegate(QObject* parent)
          : QStyledItemDelegate(parent)
      {
      
      }
      
      void TestDelegate::
      paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
      {
          static int cc = 0;
          cc++;
      
          QStyledItemDelegate::paint ( painter, option, index );
      
          QStyleOptionProgressBar progressBarOption;
          progressBarOption.rect = option.rect;
      
          int progress = cc;
      
          progressBarOption.minimum = 0;
          progressBarOption.maximum = 100;
          progressBarOption.textAlignment = Qt::AlignCenter;
          progressBarOption.progress = progress;
          progressBarOption.text = QString ( "%1%" ).arg ( progress );
          progressBarOption.textVisible = true;
          QApplication::style()->drawControl ( QStyle::CE_ProgressBar, &progressBarOption, painter );
      }
      
      MainWindow::
      MainWindow(QWidget *parent)
          : QMainWindow(parent)
      {
          createList();
          startTimer();
      }
      
      void MainWindow::
      createList()
      {
          m_model = new QStandardItemModel();
          m_model->setRowCount(1);
          m_model->setColumnCount(1);
      
          TestDelegate* delegate = new TestDelegate(this);
      
          m_list = new QListView(this);
          m_list->setModel(m_model);
          m_list->setItemDelegate(delegate);
      
          m_button = new QPushButton("Paint!", this);
          bool c = connect(m_button, SIGNAL(released()), this, SLOT(buttonPressed()));
          assert(c);
      
          QVBoxLayout* wLayout = new QVBoxLayout();
          wLayout->addWidget(m_list);
          wLayout->addWidget(m_button);
      
          QWidget* cWidget = new QWidget(this);
          cWidget->setLayout(wLayout);
      
          setCentralWidget(cWidget);
      }
      
      void MainWindow::
      startTimer()
      {
          m_timer = new QTimer(this);
          bool c = connect(m_timer, SIGNAL(timeout()), m_list, SLOT(update()));
          assert(c);
      
          m_timer->start(2000);
      }
      
      void MainWindow::
      buttonPressed()
      {
          m_list->repaint();
      }
      

      I also build the code using Qt 4.8.0 + VS2010, but result is same...no animation until move/resize. Don't know what to think...

      1 Reply Last reply
      0
      • M Offline
        M Offline
        mrjj
        Lifetime Qt Champion
        wrote on 16 Jul 2015, 23:55 last edited by mrjj
        #16

        well, that does not work for me either.
        And im on mingw compiler :)

        So thats good news :)

        its 2 in night so will first have good look tomorrow.

        1 Reply Last reply
        0
        • M Offline
          M Offline
          mrjj
          Lifetime Qt Champion
          wrote on 17 Jul 2015, 03:00 last edited by
          #17

          Hi
          Funny/strange thing was I got a project where it did work in.

          I then try to recreate it (new project) and that DID not work.
          Nearly drove me nuts so after
          3 hours of comparing/removing, i found out the following:

          if I set set a stylesheet

          MainWindow::MainWindow ( QWidget *parent )
              : QMainWindow ( parent )
          {
            createList();
            startTimer();
            setStyleSheet(QLatin1String("QFrame { border: 1px solid gray;margin-top 0px padding-top 0px}"));
          }
          

          for main window,
          It does work. (your code)

          If I do not, it does not. Same result as you. no repaint on demand/timer.

          So it seems to work if mainwin has a stylesheet ?!?

          Im a bit excited to see if it works the same for you.

          H 1 Reply Last reply 17 Jul 2015, 08:28
          1
          • M mrjj
            17 Jul 2015, 03:00

            Hi
            Funny/strange thing was I got a project where it did work in.

            I then try to recreate it (new project) and that DID not work.
            Nearly drove me nuts so after
            3 hours of comparing/removing, i found out the following:

            if I set set a stylesheet

            MainWindow::MainWindow ( QWidget *parent )
                : QMainWindow ( parent )
            {
              createList();
              startTimer();
              setStyleSheet(QLatin1String("QFrame { border: 1px solid gray;margin-top 0px padding-top 0px}"));
            }
            

            for main window,
            It does work. (your code)

            If I do not, it does not. Same result as you. no repaint on demand/timer.

            So it seems to work if mainwin has a stylesheet ?!?

            Im a bit excited to see if it works the same for you.

            H Offline
            H Offline
            hamov
            wrote on 17 Jul 2015, 08:28 last edited by
            #18

            @mrjj
            Wow!...unbelievable...but setting stylesheet for main window works for me too... :-))) I would never have thought of it. :-)) Thanks a lot for helping, this can be a workaround. :-))
            The only remaining question is how setting style sheet refers to repaint process??!... :-))

            M 1 Reply Last reply 17 Jul 2015, 08:49
            0
            • H hamov
              17 Jul 2015, 08:28

              @mrjj
              Wow!...unbelievable...but setting stylesheet for main window works for me too... :-))) I would never have thought of it. :-)) Thanks a lot for helping, this can be a workaround. :-))
              The only remaining question is how setting style sheet refers to repaint process??!... :-))

              M Offline
              M Offline
              mrjj
              Lifetime Qt Champion
              wrote on 17 Jul 2015, 08:49 last edited by mrjj
              #19

              @hamov

              Yeah blew my mind too. Glad it at least worked for you.

              The strange thing is that the stylesheet do not even alter QListView

              I have no idea why setting a stylesheet on mainwindow makes it respond to ->repaint()

              Looking at the source
              https://github.com/Vitallium/qt5/blob/master/qtbase/src/widgets/itemviews/qlistview.cpp

              There is nothing that (that i see) which could explain it.

              Update:
              After digging around more. I think the reason for ignoring update/repaint
              is that we do not change the model.
              so the view thinks it is fully updated.
              So one has to emit datachanged() somehow.
              Or actually change the data in the model.

              H 1 Reply Last reply 18 Jul 2015, 09:38
              1
              • M mrjj
                17 Jul 2015, 08:49

                @hamov

                Yeah blew my mind too. Glad it at least worked for you.

                The strange thing is that the stylesheet do not even alter QListView

                I have no idea why setting a stylesheet on mainwindow makes it respond to ->repaint()

                Looking at the source
                https://github.com/Vitallium/qt5/blob/master/qtbase/src/widgets/itemviews/qlistview.cpp

                There is nothing that (that i see) which could explain it.

                Update:
                After digging around more. I think the reason for ignoring update/repaint
                is that we do not change the model.
                so the view thinks it is fully updated.
                So one has to emit datachanged() somehow.
                Or actually change the data in the model.

                H Offline
                H Offline
                hamov
                wrote on 18 Jul 2015, 09:38 last edited by hamov
                #20

                @mrjj
                You are absolutely right. I'm created a simple model class with function updateData() which calls beginResetData() and endResetData(). Also I've changed the timer, now it is QObject::startTimer() call and QObject::timerEvent() handler. In example I didn't call update()/repaint() at all. Delegate class can be taken from previous example.
                *.hpp

                class MainWindow : public QMainWindow
                {
                    Q_OBJECT
                
                public:
                    MainWindow(QWidget *parent = 0);
                private:
                    void createList();
                protected:
                    virtual void timerEvent(QTimerEvent * event);
                private:
                    QListView* m_list;
                    TestModel* m_model;
                    int m_timerId;
                };
                

                *.cpp

                class TestModel : public QStandardItemModel
                {
                public:
                    TestModel(QObject* parent = 0);
                public:
                    void updateData();
                };
                
                TestModel::
                TestModel( QObject* parent)
                    : QStandardItemModel(parent)
                {
                }
                
                void TestModel::
                updateData()
                {
                    beginResetModel();
                    endResetModel();
                }
                
                
                MainWindow::
                MainWindow(QWidget *parent)
                    : QMainWindow(parent)
                {
                    createList();
                    m_timerId = startTimer(2000);
                }
                
                void MainWindow::
                createList()
                {
                    m_model = new TestModel();
                    m_model->setRowCount(1);
                    m_model->setColumnCount(1);
                
                    TestDelegate* delegate = new TestDelegate(this);
                
                    m_list = new QListView(this);
                    m_list->setModel(m_model);
                    m_list->setItemDelegate(delegate);
                
                    setCentralWidget(m_list);
                }
                
                void MainWindow::
                timerEvent( QTimerEvent * event )
                {
                    m_model->updateData();
                }
                

                And all works fine! I'm tested with Qt 4.8.0 but I'm sure this will work also for 5.4.2. The example works also for QTableView and QTreeView. But this isn't match my logic a bit. I think model data update and direct repaint should be independent since:

                1. There are no data in my model which need to be updated.
                2. update()/repaint() have no sense. It is enough to emit dataChanged() for repaint.

                So the conclusion of all turns:

                1. If you want to repaint view, you should update model data even if there are no data(or 'default' data).
                2. QWidget's update()/repaint() functions doesn't make sense for any View.

                Am I right?

                1 Reply Last reply
                1
                • M Offline
                  M Offline
                  mrjj
                  Lifetime Qt Champion
                  wrote on 18 Jul 2015, 10:10 last edited by mrjj
                  #21

                  @hamov said:

                  Also found out the same effect can happen by simply call
                  m_model->reset() from main window.
                  But that is bad for a tree since it resets all open states etc.

                  I think one is to use the

                  void	dataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight, const QVector<int> & roles = QVector<int> ())
                  

                  From (inside?) the model for optimized redrawing.

                  I agree with you.
                  Repaint should still repaint even if model is not dirty. Also it redraws on mousemove even
                  model is not changed so a bit odd that it then ignores direct repaints .

                  You are right.
                  I guess we can add to the conclusion
                  that if you have no data/very static , the Item-based ListWidget might work better (?)

                  update:
                  ListWidget suffer the same. update/repaint does nothing.
                  So not sure how one would go about asking it to redraw.

                  H 1 Reply Last reply 20 Jul 2015, 10:18
                  0
                  • M mrjj
                    18 Jul 2015, 10:10

                    @hamov said:

                    Also found out the same effect can happen by simply call
                    m_model->reset() from main window.
                    But that is bad for a tree since it resets all open states etc.

                    I think one is to use the

                    void	dataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight, const QVector<int> & roles = QVector<int> ())
                    

                    From (inside?) the model for optimized redrawing.

                    I agree with you.
                    Repaint should still repaint even if model is not dirty. Also it redraws on mousemove even
                    model is not changed so a bit odd that it then ignores direct repaints .

                    You are right.
                    I guess we can add to the conclusion
                    that if you have no data/very static , the Item-based ListWidget might work better (?)

                    update:
                    ListWidget suffer the same. update/repaint does nothing.
                    So not sure how one would go about asking it to redraw.

                    H Offline
                    H Offline
                    hamov
                    wrote on 20 Jul 2015, 10:18 last edited by
                    #22

                    @mrjj
                    I have tested that signal for treeview and all works fine. :-)
                    Seems update()/repaint() didn't work for any widget/view. Is it a Qt bug?...or such behavior of redraw was planned by developers?!

                    M 1 Reply Last reply 20 Jul 2015, 11:02
                    0
                    • H hamov
                      20 Jul 2015, 10:18

                      @mrjj
                      I have tested that signal for treeview and all works fine. :-)
                      Seems update()/repaint() didn't work for any widget/view. Is it a Qt bug?...or such behavior of redraw was planned by developers?!

                      M Offline
                      M Offline
                      mrjj
                      Lifetime Qt Champion
                      wrote on 20 Jul 2015, 11:02 last edited by
                      #23

                      @hamov

                      well digging around, I also found
                      m_list->viewport()->repaint();

                      which works for WidgetList. Did not test with model/view yet.

                      I think it is by design as it does redraw when data changes but we are not alone finding
                      it strange working if one google it

                      1 Reply Last reply
                      0

                      23/23

                      20 Jul 2015, 11:02

                      • Login

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