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. Minimal requirement to update a QLabel's text and show it
Forum Updated to NodeBB v4.3 + New Features

Minimal requirement to update a QLabel's text and show it

Scheduled Pinned Locked Moved Solved General and Desktop
22 Posts 4 Posters 7.4k Views 2 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.
  • JonBJ Online
    JonBJ Online
    JonB
    wrote on last edited by JonB
    #1

    I have code (Qt 5.7, all one thread for GUI + backend) which does processing and does not call QApplication::processEvents().

    Until now it just showed a QProgressBar and called setValue() as it goes along. This does get shown to the user (somewhere it must say that QProgressBar does not require an event loop to update visually).

    Now I have decided to add a QLabel to the left, to inform user what "stage" the processing is at. This is to be shown in addition to the QProgressBar.

    What is the "minimum" code I need to write to make the updated QLabel text be shown to the user? I have tried a mix of QLabel's update/hide/show() methods and none of these display the new text. The only thing I've found is QApplication::processEvents(), which does show the new text. But I really didn't want to have to use that if I don't have to.

    Is there a call to just show this QLabel's text, or just process events for that widget or its "paint" event?

    1 Reply Last reply
    0
    • JonBJ Online
      JonBJ Online
      JonB
      wrote on last edited by
      #17

      To update, say, a QLabel's text immediately so that it's shown to the user, without waiting for the main event loop to be re-entered or writing an explicit QApplication::processEvents(), turns out all you have to do is call QWidget::repaint().

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

        Hey Jon - have you considered using a QLineEdit instead of a QLabel? Set to readonly, of course.

        JonBJ 1 Reply Last reply
        0
        • mzimmersM mzimmers

          Hey Jon - have you considered using a QLineEdit instead of a QLabel? Set to readonly, of course.

          JonBJ Online
          JonBJ Online
          JonB
          wrote on last edited by
          #3

          @mzimmers
          I don't see why that would address the issue. This is a repaint question.

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

            If I understand your objective, it's an update issue. I was thinking that a change to the progress bar would signal the line edit, which would change its text accordingly. No?

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #5

              Hi,

              A QProgressBar or a QProgressDialog ? Because the later uses processEvent if modal. See the value property documentation.

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              JonBJ 1 Reply Last reply
              0
              • M Offline
                M Offline
                markus.liebe
                wrote on last edited by
                #6

                Hi, what about QProgressBar::setFormat() (http://doc.qt.io/qt-5/qprogressbar.html#format-prop) - you can use it to display text on top of the progressbar. This is not at the left of the progressbar, but it might adress your issue as well.

                1 Reply Last reply
                0
                • SGaistS SGaist

                  Hi,

                  A QProgressBar or a QProgressDialog ? Because the later uses processEvent if modal. See the value property documentation.

                  JonBJ Online
                  JonBJ Online
                  JonB
                  wrote on last edited by JonB
                  #7

                  @SGaist
                  I am using a QProgressBar as a widget, at the bottom of an overall page (QWidget). It is not some kind of QProgressDialog. But that should be neither here nor there.

                  Forget I ever mentioned QProgressBar. This is a question about when an update to the text of a QLabel is supposed to actually be "visible" to the user, when the code does QLabel.setText()s dynamically as it goes along doing something and it does not call QApplication::processEvents() (or hit the event loop). So the widget does not get a repaint event (right?). In that situation, what do I have to do to get the widget to show its new text now to the user? I am finding I must call QApplication::processEvents() for the new text to show, do I have to call that?

                  1 Reply Last reply
                  0
                  • SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #8

                    If you have a loop or something that does block the event loop, then yes, you have to call processEvents otherwise the paint request queued won't be handled by the event loop.

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    JonBJ 1 Reply Last reply
                    1
                    • SGaistS SGaist

                      If you have a loop or something that does block the event loop, then yes, you have to call processEvents otherwise the paint request queued won't be handled by the event loop.

                      JonBJ Online
                      JonBJ Online
                      JonB
                      wrote on last edited by JonB
                      #9

                      @SGaist
                      Thanks, that is indeed how I understood it. And there isn't a way to just cause paint request(s) to be processed? To force an immediate update but not other things? I see QEventLoop::ExcludeUserInputEvents, possible, I had in mind paints and only paints? All I want to do is force this text and only this text to update right now, nothing else, please!

                      1 Reply Last reply
                      0
                      • SGaistS Offline
                        SGaistS Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on last edited by
                        #10

                        One thing you can try is to add an event filter to your QLabel and ignore everything that's not a paint event.

                        Interested in AI ? www.idiap.ch
                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                        JonBJ 1 Reply Last reply
                        1
                        • SGaistS SGaist

                          One thing you can try is to add an event filter to your QLabel and ignore everything that's not a paint event.

                          JonBJ Online
                          JonBJ Online
                          JonB
                          wrote on last edited by JonB
                          #11

                          @SGaist
                          Yes, but QApplication::processEvents() sprays events all over the place, I'm more worried about what everything else might do than I am about my own widget! I just want my widget to update, or at least nothing but paint events everywhere, period! But I guess you've answered.

                          Let me ask one question though: a QProgressBar manages to update its own text/visuals (when I go QProgressBar::setValue()) without doing a QApplication::processEvents(). How does it do that?

                          1 Reply Last reply
                          0
                          • SGaistS Offline
                            SGaistS Offline
                            SGaist
                            Lifetime Qt Champion
                            wrote on last edited by
                            #12

                            If you don't want any event to be handle by the QApplication instance, then you have to do the same things a QProgressDialog: spin your own event loop.

                            Interested in AI ? www.idiap.ch
                            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                            JonBJ 1 Reply Last reply
                            0
                            • SGaistS SGaist

                              If you don't want any event to be handle by the QApplication instance, then you have to do the same things a QProgressDialog: spin your own event loop.

                              JonBJ Online
                              JonBJ Online
                              JonB
                              wrote on last edited by JonB
                              #13

                              @SGaist , or whoever,

                              OK, there is something "magic" about QProgressBar which differs from QLabel, and I need someone to explain what it is, please. Basically, a QProgressBar updates visually without my needing to call QApplication::processEvents() but a QLabel does not.

                              Consider the following sample, skeleton code:
                              Main program:

                              if __name__ == '__main__':
                                  app = QtWidgets.QApplication(sys.argv)
                              
                                  main = Main()
                              
                                  sys.exit(app.exec_())
                              

                              Main function:

                              class Main(QtWidgets.QMainWindow):
                                  def __init__(self):
                                      super().__init__()
                              
                                      self.setWindowTitle("Main")
                                      self.setGeometry(100, 100, 500, 500)
                              
                                      self.centralWidget = QtWidgets.QWidget(self)
                                      self.setCentralWidget(self.centralWidget)
                                      self.centralLayout = QtWidgets.QHBoxLayout(self.centralWidget)
                              
                                      self.lblPb = QtWidgets.QLabel()
                                      self.centralLayout.addWidget(self.lblPb)
                                      self.lblPb.setText("Initial")
                              
                                      self.pb = QtWidgets.QProgressBar()
                                      self.centralLayout.addWidget(self.pb)
                                      self.pb.setRange(0, 10)
                                      self.pb.setValue(0)
                              
                                      self.show()
                              
                                      QtCore.QTimer.singleShot(1000, self.doProgress)
                              

                              doProgress() function:

                                  def doProgress(self):
                                      import time
                                      for i in range(10 + 1):
                                          # update the label text
                                          self.lblPb.setText(str(i))
                              
                                          # We need *one* of the next two lines
                                          # to see the updated label text from above
                                          self.pb.setValue(i)
                                          # QApplication::processEvents()
                              
                                          # Yes, the next line is *deliberately* a "sleep"
                                          # It *simulates* doing some processing but *not* calling `processEvents()`
                                          time.sleep(1)
                              

                              So, I'm just setting off to call doProgress() after the main window is up & shown. Its job is to update the QProgressBar and the QLabel while in a non-event-processing-loop, to see what is visible.

                              Now, what is interesting is that the progressive QLabel.setText() is only visible because we are also calling QProgressBar.setValue(). The progress bar gets visually updated, and so does the label text. But if we remove the call to QProgressBar.setValue() we do not see the label updating. We then have to put in an explicit QApplication::processEvents() to get to see the label's new value.

                              So: what is QProgressBar.setValue() doing exactly to cause this, and where is that documented, please, please?

                              1 Reply Last reply
                              0
                              • JonBJ Online
                                JonBJ Online
                                JonB
                                wrote on last edited by
                                #14

                                Ah ha!!!

                                Googling around, I have come across QWidget::repaint(). After calling QLabel::setText(), I can just call QLabel::repaint() and I see the text immediately updated, just as wanted, without having to call QApplication::processEvents() or QProgressBar.setValue().

                                I'd still like to know what QProgressBar.setValue() does to allow the QLabel to repaint too, but I seem to have my solution.

                                May I ask: I kept asking "how can I force widget repaint without processing events", and nobody drew my attention to QWidget::repaint(). Why is that, please?

                                1 Reply Last reply
                                0
                                • SGaistS Offline
                                  SGaistS Offline
                                  SGaist
                                  Lifetime Qt Champion
                                  wrote on last edited by
                                  #15

                                  Nothing against you, I worked from memory and I had forgotten about the specifics of repaint well update VS repaint.

                                  What QProgressBar does is that it check if it needs to repaint based on internal logic and calls repaint if it turns out to be the case.

                                  Just in case, don't forget the warning and recommendation in the repaint documentation.

                                  Thanks for the reminder :)

                                  Interested in AI ? www.idiap.ch
                                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                  JonBJ 1 Reply Last reply
                                  1
                                  • SGaistS SGaist

                                    Nothing against you, I worked from memory and I had forgotten about the specifics of repaint well update VS repaint.

                                    What QProgressBar does is that it check if it needs to repaint based on internal logic and calls repaint if it turns out to be the case.

                                    Just in case, don't forget the warning and recommendation in the repaint documentation.

                                    Thanks for the reminder :)

                                    JonBJ Online
                                    JonBJ Online
                                    JonB
                                    wrote on last edited by JonB
                                    #16

                                    @SGaist
                                    Thanks, no problem. I trust you to be a guru :) I just had to understand why I was hitting my head against a brick wall, I believed there just had to be some kind of "repaint now, don't wait for event loop".

                                    It seems to be ideal for my "force update of text while doing other stuff". Just like the docs say, and yes I am aware of recursion and no I won't be inside another paintEvent!

                                    For the record, QProgressBar.setValue() must do more than just "repaint itself" (e.g. by calling repaint()). My point is, when I call QProgressBar.setValue() in addition to seeing the progressbar repaint I also see the unrelated QLabel repaint. So it must actually/presumably be doing some kind of processEvents(), allowing other widgets to paint etc. too. It's easy for me to say this, but I'd really like to see the setValue() docs have something to say about this immediate repaint/process events behaviour, as it's "unique" to QProgressBar and can be very relevant... (I know, I know, I need to start getting into raising Qt docs requests!)

                                    Meanwhile I've got what I need, and I (more or less) understand what's going on, so thank you.

                                    1 Reply Last reply
                                    0
                                    • JonBJ Online
                                      JonBJ Online
                                      JonB
                                      wrote on last edited by
                                      #17

                                      To update, say, a QLabel's text immediately so that it's shown to the user, without waiting for the main event loop to be re-entered or writing an explicit QApplication::processEvents(), turns out all you have to do is call QWidget::repaint().

                                      1 Reply Last reply
                                      0
                                      • SGaistS Offline
                                        SGaistS Offline
                                        SGaist
                                        Lifetime Qt Champion
                                        wrote on last edited by
                                        #18

                                        It doesn't, widgets are only responsible for dealing with their own updates, as for what happens to their parents, it's not them to decide. You can see the setValue implementation here.

                                        What you can also do is submit fixes for the documentation to make it clearer :)

                                        Interested in AI ? www.idiap.ch
                                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                        JonBJ 1 Reply Last reply
                                        0
                                        • SGaistS SGaist

                                          It doesn't, widgets are only responsible for dealing with their own updates, as for what happens to their parents, it's not them to decide. You can see the setValue implementation here.

                                          What you can also do is submit fixes for the documentation to make it clearer :)

                                          JonBJ Online
                                          JonBJ Online
                                          JonB
                                          wrote on last edited by
                                          #19

                                          @SGaist

                                          It doesn't

                                          Now we have a problem! Because I have posted code above which demonstrates that calling QProgressBar.setValue() not only paints itself but also causes my unrelated QLabel to get repainted. If I take out the QProgressBar.setValue() then I have to call either QApplication::processEvents() or QLabel::repaint() to see the altered text in the QLabel. So how do you explain that?? :) I agree I can't see much in the QProgressBar.setValue(), but I've given the code above from a test I did, so what's causing the QLabel to repaint when all I do is call QProgressBar.setValue()?!

                                          1 Reply Last reply
                                          0
                                          • SGaistS Offline
                                            SGaistS Offline
                                            SGaist
                                            Lifetime Qt Champion
                                            wrote on last edited by
                                            #20

                                            My point was that QProgressBar doesn't do anything special with regard to other widgets surrounding it (as you saw from its implementation). It's a border effect, nice in your case, but I wouldn't rely on it.

                                            Interested in AI ? www.idiap.ch
                                            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                            JonBJ 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