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. (seemingly) simple Qt app: creating a progress bar
Forum Updated to NodeBB v4.3 + New Features

(seemingly) simple Qt app: creating a progress bar

Scheduled Pinned Locked Moved General and Desktop
72 Posts 5 Posters 59.6k Views 1 Watching
  • 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.
  • mzimmersM Offline
    mzimmersM Offline
    mzimmers
    wrote on last edited by
    #42

    Ahh...I suppose I should have figured that out. Thanks, mlong. Just for keeping the thread "good," I should point out another error in my code:
    @ connect(&m_button, SIGNAL(clicked()), qApp, SLOT(quit()));
    @
    should actually be:
    @ connect(m_button, SIGNAL(clicked()), qApp, SLOT(quit()));
    @

    As m_button is a pointer.

    Anyway...it works! (Yes, I'm excited...I've learn to measure progress in small increments with respect to my education in Qt.) So...now that the "rude" implementation works, I'm ready to start on the more "polite" version that Volker implemented above. I'll be back with more newbie questions.

    Thanks, mlong.

    1 Reply Last reply
    0
    • M Offline
      M Offline
      mlong
      wrote on last edited by
      #43

      Ah, good catch! You're right.

      Glad to help out!

      Software Engineer
      My views and opinions do not necessarily reflect those of anyone -- living or dead, real or fictional -- in this universe or any other similar multiverse node. Void where prohibited. Your mileage may vary. Caveat emptor.

      1 Reply Last reply
      0
      • mzimmersM Offline
        mzimmersM Offline
        mzimmers
        wrote on last edited by
        #44

        Hi, Volker:

        Regarding this line:

        @connect(this, SIGNAL(requestWorkerToFinish()), m_worker, SLOT(requestFinish()));
        @

        According to the docs, requestFinish() is a signal, not a slot. Or...am I supposed to define my own slot by this name?

        1 Reply Last reply
        0
        • G Offline
          G Offline
          goetz
          wrote on last edited by
          #45

          requestFinish() is only a signal in class [[Doc:QHttp]] - unless exactly that is your worker, you will need to define that slot in your worker class and act accordingly (e.g. setting a bool variable to true and check that regularly in your loop in order to finish it prematurely).

          http://www.catb.org/~esr/faqs/smart-questions.html

          1 Reply Last reply
          0
          • M Offline
            M Offline
            mlong
            wrote on last edited by
            #46

            Which docs are you looking at?

            You're supposed to define your own slot in your thread to start the "finish everything up and shut down" process there. Thus the comment, "// you have to implement requestFinish in the worker!"

            There's nothing special about that particular slot name. Is just an example.

            Software Engineer
            My views and opinions do not necessarily reflect those of anyone -- living or dead, real or fictional -- in this universe or any other similar multiverse node. Void where prohibited. Your mileage may vary. Caveat emptor.

            1 Reply Last reply
            0
            • mzimmersM Offline
              mzimmersM Offline
              mzimmers
              wrote on last edited by
              #47

              Oops...my bad. I didn't read the documentation carefully. Thanks, guys.

              So, I defined the slot requestFinish(), which sets a bool that an "end" request was received. In my loop in run(), I test this bool. If it's true, I terminate the loop, which drops me to a file.close() and the end of the run() routine.

              I made my connect calls in my MainWindow c'tor:
              @ connect(m_button,
              SIGNAL(clicked()),
              this,
              SLOT(onQuitButtonClicked()));
              connect(this,
              SIGNAL(requestWorkerToFinish()),
              m_worker,
              SLOT(requestFinish()));
              m_worker->moveToThread(m_thread);
              @

              Now I get a run-time error:

              bq. QObject::connect: Cannot connect MainWindow::requestWorkerToFinish() to (null)::requestFinish()

              Is the reason I'm getting the (null) because I haven't yet called m_thread->start()? I guess I'm not too clear on the proper order of things in the c-tor (or if it's even OK to do this stuff in the c'tor).

              Thanks.

              1 Reply Last reply
              0
              • M Offline
                M Offline
                mlong
                wrote on last edited by
                #48

                Have you created m_worker at that point, yet? Let's see the ctor code.

                Software Engineer
                My views and opinions do not necessarily reflect those of anyone -- living or dead, real or fictional -- in this universe or any other similar multiverse node. Void where prohibited. Your mileage may vary. Caveat emptor.

                1 Reply Last reply
                0
                • mzimmersM Offline
                  mzimmersM Offline
                  mzimmers
                  wrote on last edited by
                  #49

                  I've created the pointer, but perhaps it doesn't get "populated" until the start() call?:

                  @MainWindow::MainWindow(QWidget *parent) :
                  QMainWindow(parent)
                  {
                  m_bar = new QProgressBar (this);
                  m_button = new QPushButton (this);

                  setupWidgets();

                  connect(m_button,
                  SIGNAL(clicked()),
                  this,
                  SLOT(onQuitButtonClicked()));
                  connect(this,
                  SIGNAL(requestWorkerToFinish()),
                  m_worker,
                  SLOT(requestFinish()));
                  m_worker->moveToThread(m_thread);

                  // run the run() method of the worker object once the thread has started

                  QObject::connect(m_thread, SIGNAL(started()), m_worker, SLOT(run()));

                  // enable the updating of the progress bar

                  QObject::connect(m_worker,
                  SIGNAL(percentChanged(int)),
                  this,
                  SLOT(setBarValue(int)));
                  m_thread->start();
                  }
                  @

                  1 Reply Last reply
                  0
                  • M Offline
                    M Offline
                    mlong
                    wrote on last edited by
                    #50

                    m_worker should have a value as soon as you say m_worker = new WorkerThread(); Where are you doing that? In setupWidgets()? If so, can you show that code, as well?

                    Software Engineer
                    My views and opinions do not necessarily reflect those of anyone -- living or dead, real or fictional -- in this universe or any other similar multiverse node. Void where prohibited. Your mileage may vary. Caveat emptor.

                    1 Reply Last reply
                    0
                    • mzimmersM Offline
                      mzimmersM Offline
                      mzimmers
                      wrote on last edited by
                      #51

                      Well, hell...it was there a while ago!

                      Somehow, in the movement of code from main.cpp to mainwindow.cpp, that call must have gotten lost. I put it just below the two other "new" calls in the c'tor above; is that a reasonable place for it?

                      Now, though, this line of code:
                      @ QObject::connect(m_thread, SIGNAL(started()), m_worker, SLOT(run()));
                      @
                      Is giving me this error:

                      bq. QObject::connect: Cannot connect (null)::started() to WorkerThread::run()

                      (Probably due to this, it later bombs somewhere in the start() routine.)

                      So...evidently I still don't have the order correct yet.

                      EDIT:

                      OK, I just realized I'd made the same mistake with m_thread. That too is now in the MainWindow c'tor. Duh...

                      Program now displays the main window and begins running. When I push the "close" button, I get the dialog box asking me if I really want to quit. But...the subsequent behavior is odd. When I press "no," the program exits immediately. When I press yes, it waits 3 seconds (I changed the wait() in Volker's example from 30 to 3 seconds) then I get a timed-out warning, then the program exits.

                      Is the worker thread supposed to send a signal back to mainWindow that it's completed?

                      1 Reply Last reply
                      0
                      • G Offline
                        G Offline
                        goetz
                        wrote on last edited by
                        #52

                        A QThread sends a signal that it has finished (see the docs). But for the wait call, you don't need to connect something to that signal. One would need a test run to actually see what's going wrong here.

                        Best thing in this case would be to put some qDebug() outputs in the worker thread. Make sure, that the worker actually receives the signal. For the immediate exit on "no", you should run in a debugger and step through your program to see what actually happens. Did you happen to call exit instead of return?

                        http://www.catb.org/~esr/faqs/smart-questions.html

                        1 Reply Last reply
                        0
                        • mzimmersM Offline
                          mzimmersM Offline
                          mzimmers
                          wrote on last edited by
                          #53

                          bq. Did you happen to call exit instead of return?

                          In which routine: workerThread::run()? I don't call anything there; I just let the routine run to completion:

                          @void WorkerThread::run()
                          {
                          long curr, percent;
                          string myStr;
                          static long counter = 0;

                          fileSize = getFileSize(myFile);

                          while (myFile.good() && !endSignaled)
                          {
                          myFile >> myStr;
                          curr = myFile.tellg();

                          // special handling for end of file.

                          if (curr != -1)
                          percent = curr * 100 / fileSize;
                          else
                          percent = 100;

                          counter++;
                          if ((counter % 20 == 0) || (percent == 100))
                          emit percentChanged(percent);
                          }
                          myFile.close();
                          }
                          @

                          1 Reply Last reply
                          0
                          • mzimmersM Offline
                            mzimmersM Offline
                            mzimmers
                            wrote on last edited by
                            #54

                            I'm stepping through the program in the debugger. From what I'm seeing, I'd guess that the requestFinish() slot is never getting called. When I hit close, then yes, the program continues to run in the background until EOF is hit, at which point run() ends naturally. (This brings up a side point: is it considered OK to allow the worker thread to continue until the confirmation button is hit, or should it pause when the close is hit?)

                            Here's the c'tor of my MainWindow, in case it helps:

                            @MainWindow::MainWindow(QWidget *parent) :
                            QMainWindow(parent)
                            {
                            m_bar = new QProgressBar (this);
                            m_button = new QPushButton (this);
                            m_worker = new WorkerThread ();
                            m_thread = new QThread ();

                            setupWidgets();

                            connect(m_button,
                            SIGNAL(clicked()),
                            this,
                            SLOT(onQuitButtonClicked()));

                            connect(this,
                            SIGNAL(requestWorkerToFinish()),
                            m_worker,
                            SLOT(requestFinish()));

                            // run the run() method of the worker object once the thread has started

                            QObject::connect(m_thread,
                            SIGNAL(started()),
                            m_worker,
                            SLOT(run()));

                            // enable the updating of the progress bar

                            QObject::connect(m_worker,
                            SIGNAL(percentChanged(int)),
                            this,
                            SLOT(setBarValue(int)));

                            m_worker->moveToThread(m_thread);
                            m_thread->start();
                            }
                            @

                            1 Reply Last reply
                            0
                            • mzimmersM Offline
                              mzimmersM Offline
                              mzimmers
                              wrote on last edited by
                              #55

                              I've run through the program in the debugger a few times. I'm pretty sure that the
                              m_worker->requestFinish() slot doesn't execute until the m_thread->wait() has timed out. Is it possible that the wait is somehow blocking the delivery of the slot?

                              1 Reply Last reply
                              0
                              • F Offline
                                F Offline
                                foxyz
                                wrote on last edited by
                                #56

                                Usually ,This link error means you have a member function defined but not implemented it

                                I just know coding and coding

                                1 Reply Last reply
                                0
                                • F Offline
                                  F Offline
                                  foxyz
                                  wrote on last edited by
                                  #57

                                  I'm not sure why you don't want to use just what the Qt provided. I usually use QProgessBar and QCoreApplication::processEvents to do this. like:
                                  @
                                  QProgressBar bar(...);
                                  do {
                                  do something;
                                  bar.setValue();

                                  QCoreApplication::processEvents ();
                                  

                                  }
                                  @

                                  Edit: Code formatting. Please wrap code in @ tags. -mlong]

                                  I just know coding and coding

                                  1 Reply Last reply
                                  0
                                  • mzimmersM Offline
                                    mzimmersM Offline
                                    mzimmers
                                    wrote on last edited by
                                    #58

                                    foxyz: I'm not sure I understand you...are you suggesting a different approach to what has been posted in this thread?

                                    I'm pretty sure the current implementation is close to working; I just need to find what's causing the signal not to be delivered in a timely fashion.

                                    1 Reply Last reply
                                    0
                                    • M Offline
                                      M Offline
                                      mlong
                                      wrote on last edited by
                                      #59

                                      Foxyz's proposing a non-threaded approach where you embed manual event processing within your working logic. While it is technically possible to do that, I believe the threaded approach you're taking currently is a much cleaner solution.

                                      Software Engineer
                                      My views and opinions do not necessarily reflect those of anyone -- living or dead, real or fictional -- in this universe or any other similar multiverse node. Void where prohibited. Your mileage may vary. Caveat emptor.

                                      1 Reply Last reply
                                      0
                                      • mzimmersM Offline
                                        mzimmersM Offline
                                        mzimmers
                                        wrote on last edited by
                                        #60

                                        From a novice's point of view, they both seem to have their advantages. It looks (from a first glance) that foxyz's approach would result in fewer signals/slots/connects, and that's where I seem to be stumbling right now. On the other hand, the approach that mlong and Volker are showing me is HIGHLY transferable to an existing program. Once I get this working right, it seems to be a matter of putting my (non-Qt) main code into the run() routine, establishing the sync between the worker and the UI threads, and that's it.

                                        Any idea on my question above?

                                        Thanks.

                                        1 Reply Last reply
                                        0
                                        • M Offline
                                          M Offline
                                          mlong
                                          wrote on last edited by
                                          #61

                                          While the embedded event processing has a certain appeal to it, you still are limited by the amount of work being done in between calls to processEvents(), and in certain situations you have to make sure that your GUI, etc, is not able to reenter your worker code because of getting some sort of event to restart it, otherwise things can get hairy.

                                          As for the other question, I don't have anything helpful to add at the moment...

                                          Software Engineer
                                          My views and opinions do not necessarily reflect those of anyone -- living or dead, real or fictional -- in this universe or any other similar multiverse node. Void where prohibited. Your mileage may vary. Caveat emptor.

                                          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