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.
  • 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 Offline
        JonBJ Offline
        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 Offline
            JonBJ Offline
            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 Offline
                JonBJ Offline
                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 Offline
                    JonBJ Offline
                    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 Offline
                      JonBJ Offline
                      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 Offline
                          JonBJ Offline
                          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 Offline
                            JonBJ Offline
                            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 Offline
                                JonBJ Offline
                                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
                                  • SGaistS SGaist

                                    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.

                                    JonBJ Offline
                                    JonBJ Offline
                                    JonB
                                    wrote on last edited by
                                    #21

                                    @SGaist said in Minimal requirement to update a QLabel's text and show it:

                                    It's a border effect

                                    What does that mean? Are you saying something like: the QProgressBar::repaint() call (in QProgressBar.setValue()) just happens to cause the QLabel to repaint because the widgets are close to each other, there is some overlap?

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

                                      From a quick look, it goes down to the rendering engine, I haven't read the whole implementation to determine exactly how the repainting of one of the widget triggers an update of the whole "container" widget.

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

                                      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