Results 1 to 17 of 17

Thread: update the QProgressBar

  1. #1
    Join Date
    Apr 2009
    Posts
    11
    Thanks
    1

    Default update the QProgressBar

    Hello,

    I'm building a gui over a library i have created.
    I wanted to insert a progressbar. So what i was planning to do was: enter another parameter (int) by reference/pointer to the different functions i have in my library, so i can update that value while the procedure is running. This wont be such a problem I think.

    But then: how can i tell the value has changed?
    I thought about adding a timer in a thread who checks that value every 1 second or so.
    Ok, so far so good: i created a QThread holding a timer but then i wanted to send a signal to the progressbar so the value is updated on the screen.

    I added a signal in the thread and connected it, but appearently i can't define a signal in a qthread?

    This seems a complex procedure to integrate this progressbar in the gui and to make it work.

    Could there be a more convenient solution?

    Thanx

  2. #2
    Join Date
    Jul 2008
    Location
    Germany
    Posts
    507
    Thanks
    11
    Thanked 76 Times in 74 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: update the QProgressBar

    Quote Originally Posted by aloha View Post
    but appearently i can't define a signal in a qthread?
    You can, but I don't think you need a thread at all. Just create the timer in your main window.

    Ginsengelf

  3. #3
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: update the QProgressBar

    Can we see the code?
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  4. #4
    Join Date
    Apr 2009
    Posts
    11
    Thanks
    1

    Default Re: update the QProgressBar

    Ok, the app is quite big, so i'll try to get rid of all the details.

    From a tab i can initiate a filter procedure; going like this:
    And added a timer
    Qt Code:
    1. int * state=new int(0);
    2. timerThread * theThread = new timerThread(); // create new timer
    3. theThread->setValues(m_ui->progressBar, state); // add the progressbar to update and the value to display (by pointer)
    4. theThread->run(); // run the thread who will update every 1 sec
    5. ds->Filter(min, max, state); // and initiate the filter procedure
    To copy to clipboard, switch view to plain text mode 

    As you can see, i added a pointer to the progressbar to the timer, so i dont need a signal

    When we look at run procedure the timerThread:
    Qt Code:
    1. void timerThread::run() {
    2. timer = new QTimer(); // initiate a new timer
    3. timer->setInterval(1000); // every 1 sec
    4. timer->setSingleShot(false); // keep looping untill i explicitly stop it
    5. timer->start();
    6. if ((*status) == 100) { //only stop the timer untill the procedure finished
    7. timer->stop();
    8. }
    9. else {
    10. theBar->setValue(*status); // not 100% yet => display the current value and automatically the timer will restart
    11. }
    12. }
    To copy to clipboard, switch view to plain text mode 

    It's too bad i now have to add a pointer to an integer to every function i have in my library, just to know the progress. but there most likely is no other way to do it.

    Should i encapsulate my filter procedure in a QThread, cause it doesnt seem to update now.

    Thank you

  5. #5
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: update the QProgressBar

    You can't access widgets from worker threads. Furthermore if you have a timer, you don't need a separate thread unless you are doing heavy calculations in the main thread but then your user interface will freeze regardless of using threads because widgets need to be handled in the main thread.

    You should really use the signal-slot mechanism to communicate between the progress bar and its environment. Having a shared integer variable won't do you any good. Should using signals and slots not be possible in your case, use events instead - post a custom event to the progress bar and handle the event there changing the value shown by the bar. Also remember not to starve the event loop or you won't see any progress on the bar as it will not update.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  6. The following user says thank you to wysota for this useful post:

    aloha (15th April 2009)

  7. #6
    Join Date
    Apr 2009
    Posts
    11
    Thanks
    1

    Default Re: update the QProgressBar

    Quote Originally Posted by wysota View Post
    Should using signals and slots not be possible in your case, use events instead - post a custom event to the progress bar and handle the event there changing the value shown by the bar. Also remember not to starve the event loop or you won't see any progress on the bar as it will not update.
    Thanks for your reply, i'll check out the events. If I'm correct, using events, I don't have to litter my library code with any qt related code and I just have to send every second (depending on the timer) a custom event to the progressbar.

  8. #7
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: update the QProgressBar

    With signals and slots you don't have to litter your code as well. You can always call the setValue() method (if used from the main thread) or use QMetaObject::invokeMethod with QueuedConnection parameter (from worker threads).
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  9. #8
    Join Date
    Apr 2009
    Posts
    11
    Thanks
    1

    Default Re: update the QProgressBar

    This is just some test code:

    Qt Code:
    1. timerThread::timerThread() {
    2. timer = new QTimer();
    3. connect( timer, SIGNAL(timeout()), this, SLOT(sendValue()));
    4. }
    5.  
    6. void timerThread::setValues(QProgressBar * s, int * state) {
    7. status=state;
    8. theBar=s;
    9. }
    10.  
    11.  
    12. void timerThread::run() {
    13. timer->setInterval(1000);
    14. timer->start();
    15. }
    16. */
    17. }
    18.  
    19. // this will be executed when the timer has finished
    20. void timerThread::sendValue() {
    21. if (*status <= 100) {
    22. timer->start();
    23. }
    24. theBar->setValue(*status);
    25. }
    To copy to clipboard, switch view to plain text mode 

    I can't see how you think this will work without putting the timer in a thread.
    As the timer and the filter process have to run simultaneously.
    Now i get an error when i run it: it cant seem to find the slot 'sendValue()'
    Qt Code:
    1. Object::connect: No such slot QThread::sendValue() in timerThread.cpp:6
    To copy to clipboard, switch view to plain text mode 

    Any ideas?
    Last edited by aloha; 15th April 2009 at 20:09.

  10. #9
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: update the QProgressBar

    I'm guessing you forgot to add the Q_OBJECT macro to the thread class but the real problem is accessing the widget from within a worker thread which is forbidden. Also remember the thread object lives in the thread that created the object and not in the thread that the object controls. Therefore slots from this object will be executed in context of the main thread which is probably blocked by some heavy calculation or else you wouldn't be spawning the worker thread at all.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  11. #10
    Join Date
    Apr 2009
    Posts
    11
    Thanks
    1

    Default Re: update the QProgressBar

    I cant seem to find much information about Qevents.
    I think i still need signal and slot communication in my timer because I've got to know when the timer time's out. Or can I also do that using slots, maybe?

    Imagine that this works, then i still need to send a slot to the mainwindow. Which i had to pass on by pointer to the thread, so then i guess I'm still accessing a widget within a worker thread which is forbidden?

    Looking at my previous post, can anybody tell me where just to place those QEvents, cause it seems harder than expected.

    Thank you!

  12. #11
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: update the QProgressBar

    Quote Originally Posted by aloha View Post
    I think i still need signal and slot communication in my timer because I've got to know when the timer time's out. Or can I also do that using slots, maybe?
    Yes, you can. See QObject::startTimer(), QObject::killTimer() and QObject::timerEvent().

    Imagine that this works, then i still need to send a slot to the mainwindow. Which i had to pass on by pointer to the thread, so then i guess I'm still accessing a widget within a worker thread which is forbidden?
    Sending a signal doesn't involve accessing the receiver directly. Only making the connection does but it is thread safe.

    Looking at my previous post, can anybody tell me where just to place those QEvents, cause it seems harder than expected.
    See docs for QObject::customEvent() and follow the links.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  13. #12
    Join Date
    Apr 2009
    Posts
    11
    Thanks
    1

    Default Re: update the QProgressBar

    In my filter call I know have the following:
    Qt Code:
    1. state=new double(0); // initialize the member variable
    2. cout << *state << endl; // prints 0
    3. updateProgressBar * me=new updateProgressBar(state, this); // this holds the timer and the events with a pointer to the state
    4.  
    5. ds->Filter(min, max,s, state); // pass the same pointer to state to check on the progress
    To copy to clipboard, switch view to plain text mode 

    the updateProgressBar code:
    Qt Code:
    1. updateProgressBar::updateProgressBar(double* state, QObject *parent)
    2. : status(state), pa(parent), QObject(parent) // initialize
    3. {
    4. startTimer(20); // update every 20 miliseconds
    5. }
    6.  
    7. // this will be called when the timer times out
    8. void updateProgressBar::timerEvent(QTimerEvent *event)
    9. {
    10. std::cout << "Timer ID:" << event->timerId() << std::endl;
    11. if (*status==100) { // finished?
    12. killTimer(event->timerId());
    13. }
    14. std::cout << "sending " << *status << std::endl; // !!!
    15. const QEvent::Type MyEvent = (QEvent::Type)1234;
    16. QEvent * message=new QEvent(MyEvent);
    17. QCoreApplication::sendEvent(pa, message);
    18. }
    To copy to clipboard, switch view to plain text mode 

    And i receive the event in my parent frame:

    Qt Code:
    1. void intensityframe2::customEvent(QEvent * events) {
    2. cout << "received an event" << endl;
    3. int value=(*state); //cast to int
    4. m_ui->progressBar->setValue(value); //display on the screen
    5. }
    To copy to clipboard, switch view to plain text mode 
    This code works, but i've got one pointer problem.
    After even one timer loop, i display the value of the pointer (see !!!) and then i send an event to the parent window so he knows he has to check on the value of the state/progress and display it. But even when no assignments have been made to value of the pointer is set to a strange value: like for example: 2.1305e-313

    The value of that double is allocated on the heap, so i dont immediately see a reason why the value of that pointer isnt just 0 and not 2.1305e-313 or so...

    ps: even when i place the timer in my mainwindow and delete the updateProgressBar class, the value gets changed :/
    Last edited by aloha; 17th April 2009 at 13:19.

  14. #13
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: update the QProgressBar

    I don't understand why you are passing that pointer to double around.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  15. #14
    Join Date
    Apr 2009
    Posts
    11
    Thanks
    1

    Default Re: update the QProgressBar

    the filtering is done in my library, i'm running this operation through the command
    ds->Filter(...);
    how else can I know how much computation is already completed without passing a pointer?
    The filteroperation is a function, not an object, so i cant have a public member function or so.
    During the filter process i can update that status (pointer to double) and in my gui i have a timer who checks the value of that pointer every 0.2 seconds.

    I need to have access to the same value from two sections of my application.
    1) Write access for the filterfunction, to update the status of the progress
    2) read access for the gui to read the value of the current progress

    Don't think there is another decent/better way to accomplish this

  16. #15
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: update the QProgressBar

    Quote Originally Posted by aloha View Post
    how else can I know how much computation is already completed without passing a pointer?
    That's what the setValue() method in the progress bar is for, isn't it?

    The filteroperation is a function, not an object, so i cant have a public member function or so.
    During the filter process i can update that status (pointer to double) and in my gui i have a timer who checks the value of that pointer every 0.2 seconds.
    Let's temporarily forget accessing a shared variable from within multiple threads is WRONG... Updating the variable (why is it created on heap anyway?) won't do you any good because you have to inform the environment that you have actually changed it. You try to get away from it by wasting computer cycles with the timer but it's a bad approach. You should say "hey, my progress value has changed to 3.14!" instead. You can do that either by emitting a signal or by posting an event that carries the value (the latter is probably better in your case as you can do that from an arbitrary point in your code).

    Don't think there is another decent/better way to accomplish this
    I hate to be rude but the one you picked is far from being decent. What happens if you read the value from one thread while it is being overwritten by the other thead? You'll get a bogus value. In your case it's not that dangerous, you'll just get a wrong progress value for a while but in a general case this can blow up the world.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  17. #16
    Join Date
    Apr 2009
    Posts
    11
    Thanks
    1

    Default Re: update the QProgressBar

    Quote Originally Posted by wysota View Post
    That's what the setValue() method in the progress bar is for, isn't it?



    Let's temporarily forget accessing a shared variable from within multiple threads is WRONG... Updating the variable (why is it created on heap anyway?) won't do you any good because you have to inform the environment that you have actually changed it. You try to get away from it by wasting computer cycles with the timer but it's a bad approach. You should say "hey, my progress value has changed to 3.14!" instead. You can do that either by emitting a signal or by posting an event that carries the value (the latter is probably better in your case as you can do that from an arbitrary point in your code).



    I hate to be rude but the one you picked is far from being decent. What happens if you read the value from one thread while it is being overwritten by the other thead? You'll get a bogus value. In your case it's not that dangerous, you'll just get a wrong progress value for a while but in a general case this can blow up the world.
    Ok , let's start again, i've got no threads. I've got a mainwindow that starts a filterfunction. Now i want to add a progressbar reporting the progress of the filteroperation.
    The filterfunction is in another file. how can i have access to the state of the progress of the filterfunction? My suggestion was to pass an integer/double by reference/pointer that I update during the filter progress. For example, i filter 5 different things, so the value of that integer/double will be incremeted every time by 20 (0%, 20%, 40% .... 100%)

    Now, to update the progressbar on the screen, i need a timer to check like every 0.2 seconds the value of that passed integer/double. That's why i need the QTimer.
    And i use the QTimerEvent to know when the timer has timed out and when to update the value on the screen.

    If you can tell me another way how to check on the status/progress of a procedure without passing an integer/double that holds the status, please do...

  18. #17
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: update the QProgressBar

    Use signals and slots.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


Similar Threads

  1. Problem in QProgressBar update
    By nikhilqt in forum Qt Programming
    Replies: 0
    Last Post: 10th March 2009, 10:20
  2. Qt Update project - Opinions wanted
    By pvdk in forum Qt Programming
    Replies: 0
    Last Post: 8th November 2008, 08:41
  3. Paintevent and update
    By csvivek in forum Qt Programming
    Replies: 1
    Last Post: 25th March 2008, 07:09
  4. QPainter update()
    By csvivek in forum Qt Programming
    Replies: 5
    Last Post: 24th March 2008, 09:42
  5. QSlider Update Problem
    By December in forum Qt Programming
    Replies: 4
    Last Post: 10th September 2006, 04:02

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.