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. Which is the proper way to update Qprogressbar from a widget
QtWS25 Last Chance

Which is the proper way to update Qprogressbar from a widget

Scheduled Pinned Locked Moved General and Desktop
11 Posts 3 Posters 5.3k 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
    marceloarguello700
    wrote on last edited by
    #1

    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
    0
    • dheerendraD Offline
      dheerendraD Offline
      dheerendra
      Qt Champions 2022
      wrote on last edited by
      #2

      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
      0
      • A Offline
        A Offline
        andreyc
        wrote on last edited by
        #3

        @
        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
        0
        • dheerendraD Offline
          dheerendraD Offline
          dheerendra
          Qt Champions 2022
          wrote on last edited by
          #4

          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
          0
          • M Offline
            M Offline
            marceloarguello700
            wrote on last edited by
            #5

            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
            0
            • A Offline
              A Offline
              andreyc
              wrote on last edited by
              #6

              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
              0
              • A Offline
                A Offline
                andreyc
                wrote on last edited by
                #7

                [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
                0
                • M Offline
                  M Offline
                  marceloarguello700
                  wrote on last edited by
                  #8

                  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
                  0
                  • A Offline
                    A Offline
                    andreyc
                    wrote on last edited by
                    #9

                    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
                    0
                    • M Offline
                      M Offline
                      marceloarguello700
                      wrote on last edited by
                      #10

                      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
                      0
                      • A Offline
                        A Offline
                        andreyc
                        wrote on last edited by
                        #11

                        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
                        0

                        • Login

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