Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. QLabel stops updating (setText does not work)
Forum Updated to NodeBB v4.3 + New Features

QLabel stops updating (setText does not work)

Scheduled Pinned Locked Moved Solved Qt for Python
9 Posts 3 Posters 5.2k 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.
  • A Offline
    A Offline
    appleren
    wrote on last edited by appleren
    #1

    Edit:
    Short Answer: My problem was using threads for updating GUI elements. Using QThread and pyqtSignals solved my issue.

    I am using PyQt5.
    I designed a gui which gets necessary data values from a running thread and displays the values in the QLabel objects of the gui.
    The data obtained are changing continuously and very frequently. I use another thread for updating the label texts continuously.
    The problem is, this operation works well in the beginning but after a short time, labels stop showing the real most recent value, the gui just stops displaying new values, the latest value before the breakdown remains until I halt the program.
    The thing is, I am sure I feed the setText method the correct (most recent) values, and when I print the label.text() values after trying to set the text, it prints the correct values here too. So I think labels actually have correct text but GUI does not display them after a short time, it just stops updating.

    What is the soluttion for this? I need to keep updating the values in the gui for an indefinite amount of time. Any help is appreciated. If necessary, my code for updating is below:

     def updateValues(self):
            while self.condition:
                self.values_dict = self.values_listener_func()
                print("GUI VALUES DICT:\n", self.values_dict) # values are printed correctly even after gui update stops
                for title in self.values_dict:
                    self.value_labels[title].setText(str(self.values_dict [title]))
                    print(self.value_labels[title].text())  
                    # values are printed correctly even after gui update stops 
                    # which means label texts are actually changed but not displayed
                QtWidgets.QApplication.processEvents()    # does not fix not updating problem
                time.sleep(self.wait_time)
    
    JonBJ 1 Reply Last reply
    0
    • A appleren

      Edit:
      Short Answer: My problem was using threads for updating GUI elements. Using QThread and pyqtSignals solved my issue.

      I am using PyQt5.
      I designed a gui which gets necessary data values from a running thread and displays the values in the QLabel objects of the gui.
      The data obtained are changing continuously and very frequently. I use another thread for updating the label texts continuously.
      The problem is, this operation works well in the beginning but after a short time, labels stop showing the real most recent value, the gui just stops displaying new values, the latest value before the breakdown remains until I halt the program.
      The thing is, I am sure I feed the setText method the correct (most recent) values, and when I print the label.text() values after trying to set the text, it prints the correct values here too. So I think labels actually have correct text but GUI does not display them after a short time, it just stops updating.

      What is the soluttion for this? I need to keep updating the values in the gui for an indefinite amount of time. Any help is appreciated. If necessary, my code for updating is below:

       def updateValues(self):
              while self.condition:
                  self.values_dict = self.values_listener_func()
                  print("GUI VALUES DICT:\n", self.values_dict) # values are printed correctly even after gui update stops
                  for title in self.values_dict:
                      self.value_labels[title].setText(str(self.values_dict [title]))
                      print(self.value_labels[title].text())  
                      # values are printed correctly even after gui update stops 
                      # which means label texts are actually changed but not displayed
                  QtWidgets.QApplication.processEvents()    # does not fix not updating problem
                  time.sleep(self.wait_time)
      
      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @appleren
      You need to write code differently for an event-driven UI like Qt. You must not used a call like time.sleep(self.wait_time). Nor should you have a while self.condition This blocks Qt's event loop which services the UI. That is why you do not see your updates. And try not to use QtWidgets.QApplication.processEvents() either, it can be useful but is usually indicative of a design problem.

      If you need a timer you would use a QTimer.

      I designed a gui which gets necessary data values from a running thread and displays the values in the QLabel objects of the gui.

      The data obtained are changing continuously and very frequently. I use another thread for updating the label texts continuously.

      I don't know if your thread is necessary or if its code is good. If you need to do this you must be using signals from the thread. You cannot and must not directly update a GUI element from another thread, if that is what you are doing.

      A 1 Reply Last reply
      2
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #3

        Hi and welcome to devnet,

        Beside the good point of @JonB, do not access GUI elements from a different thread.

        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
        1
        • JonBJ JonB

          @appleren
          You need to write code differently for an event-driven UI like Qt. You must not used a call like time.sleep(self.wait_time). Nor should you have a while self.condition This blocks Qt's event loop which services the UI. That is why you do not see your updates. And try not to use QtWidgets.QApplication.processEvents() either, it can be useful but is usually indicative of a design problem.

          If you need a timer you would use a QTimer.

          I designed a gui which gets necessary data values from a running thread and displays the values in the QLabel objects of the gui.

          The data obtained are changing continuously and very frequently. I use another thread for updating the label texts continuously.

          I don't know if your thread is necessary or if its code is good. If you need to do this you must be using signals from the thread. You cannot and must not directly update a GUI element from another thread, if that is what you are doing.

          A Offline
          A Offline
          appleren
          wrote on last edited by
          #4

          @JonB
          First of all thanks for the answer. Actually I do not have much experience with PyQt, so thanks for the warnings and it would be great if you could explain more:

          • The "updateValues " function I wrote above is a thread's target function, thats what I meant by "I use a thread for updating the label texts continuously". "values_listener_func" is the function for obtaining the most recent data, so it returns different values in each iteration. I have a main class for the GUI and I start this thread within the class to update the label values.
            Is this a problem, if yes what approach should I use?
          • I can look into QTimer and use it instead of sleep function, but how is using "while condition" wrong and how can I correct it?

          Thanks.

          JonBJ 1 Reply Last reply
          0
          • A appleren

            @JonB
            First of all thanks for the answer. Actually I do not have much experience with PyQt, so thanks for the warnings and it would be great if you could explain more:

            • The "updateValues " function I wrote above is a thread's target function, thats what I meant by "I use a thread for updating the label texts continuously". "values_listener_func" is the function for obtaining the most recent data, so it returns different values in each iteration. I have a main class for the GUI and I start this thread within the class to update the label values.
              Is this a problem, if yes what approach should I use?
            • I can look into QTimer and use it instead of sleep function, but how is using "while condition" wrong and how can I correct it?

            Thanks.

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

            @appleren said in QLabel stops updating (setText does not work):

            The "updateValues " function I wrote above is a thread's target function

            I have a main class for the GUI and I start this thread within the class to update the label values.

            If you mean: you run updateValues() in a non-main-UI thread, then that is your problem. Are you saying this? That violates that you must not update or even access the UI from any thread other than its own.

            If you need a thread to cause the UI to update, you have to send signals with the necessary data and connect the main UI thread with a slot to do the UI updates required.

            A 1 Reply Last reply
            3
            • JonBJ JonB

              @appleren said in QLabel stops updating (setText does not work):

              The "updateValues " function I wrote above is a thread's target function

              I have a main class for the GUI and I start this thread within the class to update the label values.

              If you mean: you run updateValues() in a non-main-UI thread, then that is your problem. Are you saying this? That violates that you must not update or even access the UI from any thread other than its own.

              If you need a thread to cause the UI to update, you have to send signals with the necessary data and connect the main UI thread with a slot to do the UI updates required.

              A Offline
              A Offline
              appleren
              wrote on last edited by appleren
              #6

              @JonB
              Yes, I was using a non-main thread (threading.Thread object) to update the labels. The thing is, I use the exact same method for another similar task (updating an image on the GUI continuously), and that worked great, without any problems. My aim is to make the same thing work with the "values labels". Then I will run these two operations, one will update the values of the labels and other one will update the image continuously. These work independent from each other. Thats why I was using threads.

              Now I understand that using a non-main thread to update GUI is not healthy. But I have some questions:

              • Why does the thread which updates the image work (image is displayed with a QLabel too), but the other thread which updates multiple labels does not work properly (it actually works for a few seconds, then it breaks down)?
              • From your answer I understand that I should use QThreadinstead of a threading.Thread and use signals. https://stackoverflow.com/a/9964621/9181308 would a solution like this suffice, with a while True loop in the thread class' run method (because values change constantly)? And is using time.sleep in the loop still dangerous even though the non-main thread does not access GUI elements directly (I will use a QThread and using signals to use main thread to update the labels)?
              JonBJ 1 Reply Last reply
              0
              • A appleren

                @JonB
                Yes, I was using a non-main thread (threading.Thread object) to update the labels. The thing is, I use the exact same method for another similar task (updating an image on the GUI continuously), and that worked great, without any problems. My aim is to make the same thing work with the "values labels". Then I will run these two operations, one will update the values of the labels and other one will update the image continuously. These work independent from each other. Thats why I was using threads.

                Now I understand that using a non-main thread to update GUI is not healthy. But I have some questions:

                • Why does the thread which updates the image work (image is displayed with a QLabel too), but the other thread which updates multiple labels does not work properly (it actually works for a few seconds, then it breaks down)?
                • From your answer I understand that I should use QThreadinstead of a threading.Thread and use signals. https://stackoverflow.com/a/9964621/9181308 would a solution like this suffice, with a while True loop in the thread class' run method (because values change constantly)? And is using time.sleep in the loop still dangerous even though the non-main thread does not access GUI elements directly (I will use a QThread and using signals to use main thread to update the labels)?
                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by
                #7

                @appleren
                I hoped you would get an answer from someone other than me as I am not a great fans of threads. But not so far.

                If a non-UI thread worked for you at updating the UI you were "lucky". So you might get away in some circumstances but not others for no discernible reason.

                At the time I first saw your while True, and your time.sleep(), I did not know that was in a thread. That makes it only potentially more acceptable. It depends what your values_listener_func() does. It's true now that you won't block the GUI thread, but nonetheless you don't want your thread to chew up CPU time.

                The Qt way of doing this would be to have a QTimer ticking and you read the data each time that expires, rather than a blocking loop with a sleep. Using Python with Qt I do not know what the interactions between Qt threads, Python threads and time.sleep() is.

                The other possibility is: are you sure you need a thread at all? A large number of newcomers jump straight into threads when they are not necessary. If you just had the main GUI thread with a QTimer used to pull the next batch of samples which have arrived every so often, would that simply achieve whatever you are doing now?

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

                  If you need to generate images for your labels in a different thread, then you might want to check the Mandelbrot Example.

                  Do not use while(true), always have a mean to exit your mane loop cleanly.

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

                    @JonB @SGaist
                    Thanks for all the help.

                    Using the approach I mentioned above (Using signals with QThread: https://stackoverflow.com/a/9964621/9181308) solved my problem.

                    I still do not get this:

                    • Why does the thread which updates the image work (image is displayed with a QLabel too), but the other thread which updates multiple labels does not work properly (it actually works for a few seconds, then it breaks down)?

                    It was like this every single time I ran the program, in a few different computers, so I don't know how it is "luck", but I am not concerned with this right now.

                    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