Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct

    Which is the proper way to update Qprogressbar from a widget

    General and Desktop
    3
    11
    4835
    Loading More Posts
    • 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
      marceloarguello700 last edited by

      I read some post, but dont find the solution
      I read thinks like:
      The gui may only be controlled by the main thread,
      You can't modify GUI objects from another thread,
      Must to use QMetaType.

      But i need a short example.
      My scenario is , in a mainwindow have a mapframe for drawing, it inherit Qwidget
      and emit two signal:
      In the mapframe.header have:
      signals:

      @ void drawingProgress( int, int );
      void xyCoordinates( const QPointF & p );// current mouse position
      @

      Inside of mapframe paintEvent have a for that render points:

      @
      void MapFrame::paintEvent(QPaintEvent * /* event */)

      for (int i=0;i<m_PointFeatures.size();i++)
      {
      painter->setBrush(m_PointFeatures.at(i).color);
      painter->drawEllipse(translator.mapToPixel(m_PointFeatures.at(i).x,m_PointFeatures.at(i).y), 3, 3);
      if( i % 1000==0)
      {
      emit drawingProgress(m_PointFeatures.size(),i);
      }
      }
      @

      The mapframe is inside of manwindow
      in the constructor of main window, connect the signals to the slots:

      @
      connect( mapframe, SIGNAL( xyCoordinates( const QPointF & ) ),
      this, SLOT( showMouseCoordinate( const QPointF & ) ) );

       connect( mapframe, SIGNAL( drawingProgress(int,int ) ),
                this, SLOT( showDrawingProgress( int,int ) ) );
      

      @


      When update mouse coordenates to a Qlabel
      it work ok:

      @
      void dlgGraph::showMouseCoordinate( const QPointF & pt)
      {
      lbMousePosition->setText(QString("Lat:%1,Long:%2").arg(pt.x(),0,'f',5).arg(pt.y(),0,'f',5));
      }
      @
      But when update the QProgressBar, iot crash the main window:

      @
      void dlgGraph::showDrawingProgress(int t,int i)
      {
      qDebug()<< i;
      progressBar->setMaximum(t);
      progressBar->setValue(i);//->CRASH
      }
      @

      How make a proper implementation of it?

      1 Reply Last reply Reply Quote 0
      • dheerendra
        dheerendra Qt Champions 2022 last edited by

        Signals and Slots is the best way to update the same. Since you are doing everything inside the main thread(painting and updating the progress bar), you need to process the events locally. Program may be crashing due to some wrong values or huge values.

        You can try something like following. Just simulated your scenario.

        @void Widget::paintEvent(QPaintEvent *){
        int count=10;
        qDebug() << "Painting"<<endl;
        for (int i=0; i<100000000;i++){
        if (i ==0){
        qDebug() << " i="<<i << endl;
        QThread::sleep(1);
        updateprogbar(count);
        count+=10;
        }
        }
        }

        void Widget::updateprogbar(int i){
        qDebug() << " UpdateBar="<<i << endl;
        QEventLoop loop;
        this->bar->setValue(i);
        loop.processEvents();
        }
        @

        Dheerendra
        @Community Service
        Certified Qt Specialist
        http://www.pthinks.com

        1 Reply Last reply Reply Quote 0
        • A
          andreyc last edited by

          @
          void dlgGraph::showDrawingProgress(int t,int i)
          {
          qDebug()<< i;
          progressBar->setMaximum(t);
          progressBar->setValue(i);//->CRASH
          }
          @

          May be a silly question but have you allocated progressBar ?
          Another question is why do you set maximum on each call to showDrawingProgress?
          One time before starting a loop is enough.
          What are values of t and i in showDrawingProgress when it crashes?
          Does it crash immediately on a first call or after some time?

          I would suggest to connect QProgressBar::setRange and QProgressBar::setValue to the signals in mapframe and them emit setRange before starting a loop and emit setValue in the loop.

          1 Reply Last reply Reply Quote 0
          • dheerendra
            dheerendra Qt Champions 2022 last edited by

            Good point andreyc. I did not suspect on ProgressBar allocation as the crash is in setValue. If it crashes at line#, allocation should be definitely a problem and it should crash every time.

            Dheerendra
            @Community Service
            Certified Qt Specialist
            http://www.pthinks.com

            1 Reply Last reply Reply Quote 0
            • M
              marceloarguello700 last edited by

              The progresbar is outside of widget.
              What mean allocated,
              i add the progress to the layout:

              @
              progressBar = new QProgressBar() ;
              progressBar->setRange(0,100);
              mainLayout->addWidget(progressBar);
              @

              Now in mapframe.h split the signal and add another signal to setBarMaxValue
              before the for init.

              @
              void progressMaxValue(int);
              void progressDrawValue(int);
              @

              In the main window connect the signal to slot
              @
              connect( mapframe, SIGNAL( progressDrawValue(int ) ),
              this, SLOT( setBarValue( int ) ) );
              connect( mapframe, SIGNAL( progressMaxValue(int) ),
              this, SLOT( setBarMaxValue( int ) ) );
              @

              The paint even of the MapFrame widget emit the signal progressMaxValue
              before starting the for loop.

              @
              void MapFrame::drawPointFeatures(QPainter *painter)
              {

              if (m_PointFeatures.size()>0)
              {
              emit progressMaxValue(m_PointFeatures.size());
              }
              for (int i=0;i<m_PointFeatures.size();i++)
              {
                    painter->setBrush(m_PointFeatures.at(i).color);
                    painter->drawEllipse(translator.mapToPixel(m_PointFeatures.at(i).x,m_PointFeatures.at(i).y), 3, 3);          
                    if( 1 % 1000==0) emit progressDrawValue(i);
              }
              

              }
              @

              It crash in the first emit when i=0
              Greetings

              1 Reply Last reply Reply Quote 0
              • A
                andreyc last edited by

                Do you work on Windows on OSX, Linux?
                If OSX,Linux could show a backtrace for the crash?
                I don't know how to get backtrace on Windows but if you know how then it may help here.

                1 Reply Last reply Reply Quote 0
                • A
                  andreyc last edited by

                  [quote author="marceloarguello700" date="1410970001"]
                  The progresbar is outside of widget.
                  What mean allocated,
                  i add the progress to the layout:

                  @
                  progressBar = new QProgressBar() ; // <<-- here is allocation
                  progressBar->setRange(0,100);
                  mainLayout->addWidget(progressBar);
                  @
                  [/quote]

                  Yes, you allocated a progress bar

                  [quote author="marceloarguello700" date="1410970001"]
                  @
                  void MapFrame::drawPointFeatures(QPainter *painter)
                  {

                  if (m_PointFeatures.size()>0)
                  {
                  emit progressMaxValue(m_PointFeatures.size());
                  }
                  for (int i=0;i<m_PointFeatures.size();i++)
                  {
                        painter->setBrush(m_PointFeatures.at(i).color);
                        painter->drawEllipse(translator.mapToPixel(m_PointFeatures.at(i).x,m_PointFeatures.at(i).y), 3, 3);          
                        if( 1 % 1000==0) emit progressDrawValue(i);
                  }
                  

                  }
                  @
                  [/quote]

                  I guess it is a type in the comment and in the source code you have
                  @
                  if( i % 1000==0) emit progressDrawValue(i);
                  @

                  instead of
                  @
                  if( 1 % 1000==0) emit progressDrawValue(i);
                  @

                  1 Reply Last reply Reply Quote 0
                  • M
                    marceloarguello700 last edited by

                    Thanks for the reply,
                    I run over window

                    My original code is with i, dont know, why appear a one (1)
                    @
                    if( i % 1000==0) emit progressDrawValue(i);
                    @

                    the question is what need to make to avoid crashing?

                    1 Reply Last reply Reply Quote 0
                    • A
                      andreyc last edited by

                      You may try to connect the progressDrawValue and progressMaxValue directly to QProgressBar

                      @
                      connect( mapframe, SIGNAL( progressDrawValue(int ) ),
                      progressBar, SLOT( setValue( int ) ) );
                      connect( mapframe, SIGNAL( progressMaxValue(int) ),
                      progressBar, SLOT( setMaximum( int ) ) );
                      @

                      1 Reply Last reply Reply Quote 0
                      • M
                        marceloarguello700 last edited by

                        I try like you suggest but crash in the firts emit

                        According to this page
                        http://qt-project.org/doc/qt-4.8/threads-qobject.html

                        If you are calling a function on an QObject subclass that doesn't
                        live in the current thread and the object might receive events,
                        you must protect all access to your QObject subclass's internal
                        data with a mutex; otherwise, you may* experience crashes* or other undesired behavior.

                        May be it is the cause, but i dont know how fix it.

                        1 Reply Last reply Reply Quote 0
                        • A
                          andreyc last edited by

                          Do you have MapFrame::drawPointFeatures and QProgressBar in separate threads ?

                          If so, then it will not work. All UI related classes must be used in a "main thread":http://qt-project.org/doc/qt-5/threads-qobject.html#qobject-reentrancy.

                          1 Reply Last reply Reply Quote 0
                          • First post
                            Last post