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. PyQt5 display variable from Thread to LCD
Forum Updated to NodeBB v4.3 + New Features

PyQt5 display variable from Thread to LCD

Scheduled Pinned Locked Moved Unsolved General and Desktop
12 Posts 4 Posters 4.8k 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.
  • W Offline
    W Offline
    webgiorgio
    wrote on 11 Aug 2018, 15:26 last edited by
    #1

    Hello,
    I am learning python3.6 and Qt5 on Ubuntu one month so far.

    I made this program where I print the value of "i" in the terminal every second, 0 to 9.
    I would like to show "i" in the LCD of the GUI, but after a few hours of attempt with signals-slots I am stuck.
    How to I get the values of "i" into the variable "v"?
    What if I also want to use in the Thread the status of the checkbox?

    Note that the slider and progress bar only serve the purpose of verifying that the GUI is not frozen.

    import sys
    from PyQt5.QtCore import Qt
    from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider, QProgressBar,
        QVBoxLayout, QApplication, QCheckBox )
    from PyQt5.QtCore import QThread, pyqtSignal
    
    import time
    
    class Example(QWidget):
        def __init__(self):
            super().__init__()
            self.initUI()
            
        def initUI(self):
            cb  = QCheckBox("enable countdown")
            lcd = QLCDNumber(self)
            pro = QProgressBar(self)
            sld = QSlider(Qt.Horizontal, self)
    
            vbox = QVBoxLayout()
            vbox.addWidget(cb)
            vbox.addWidget(lcd)
            vbox.addWidget(pro)
            vbox.addWidget(sld)
    
            self.setLayout(vbox)
            
            #link the slider to the progress bar
            sld.valueChanged.connect(pro.setValue)
            
            #show i in the lcd
            v=15
            lcd.display(v)
            
            self.setGeometry(300, 300, 250, 150)
            self.setWindowTitle('Signal and slot')
            self.show()
            
            self.countdown()
        
        def countdown(self):
            self.wt=WorkerThread()
            self.wt.start()
    
               
    
    class WorkerThread(QThread):
        def __init__(self, parent=None):
            super(WorkerThread, self).__init__(parent)
        
        def run(self):
            x = 10
            for i in range(x):
               time.sleep(1)
               print(i) 
            
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        ex = Example()
        sys.exit(app.exec_())
    
    1 Reply Last reply
    0
    • S Offline
      S Offline
      SGaist
      Lifetime Qt Champion
      wrote on 11 Aug 2018, 18:56 last edited by
      #2

      Hi and welcome to devnet,

      You should emit a signal from your thread that you’ll connect to a slot that will update the LCD and the variable.

      And also add a slot to your thread that you’ll connect to your checkbox.

      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
      2
      • W Offline
        W Offline
        webgiorgio
        wrote on 11 Aug 2018, 20:18 last edited by
        #3

        Hi, thanks for your hint.
        I understand the logic you pointed out, but I know so little PyQt that I don't know how to implement what you suggested.

        I managed to solve half of the problem. The signal for the value of "i" works, for the checkbox it only works with the method I commented out. When I insert it in the "run" method, I get the error: "TypeError: run() missing 1 required positional argument: 'b'". I don't know how to address it

        #!/usr/bin/env python3
        # -*- coding: utf-8 -*-
        """
        Created on Sat Aug 11 15:48:57 2018
        
        """
        
        import sys
        from PyQt5.QtCore import Qt
        from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider, QProgressBar,
            QVBoxLayout, QApplication, QCheckBox )
        from PyQt5.QtCore import QThread, pyqtSignal
        
        import time
        
                   
        
        class WorkerThread(QThread):
            signal_i=pyqtSignal( int, name='Signal_i') ### 1) declare the signal
            
            def __init__(self, parent=None):
                QThread.__init__(self)
                #super(WorkerThread, self).__init__(parent)
           
            def run(self, b):
                if b == 0:
                    print ("non checked")
                else:
                    print("checked")
                
                x = 10
                for i in range(x):
                   time.sleep(1)
                   #print(i) 
                   self.signal_i.emit(i)  ### 2) emitt the signal
                
                
        class Example(QWidget):
            def __init__(self):
                super().__init__()
                self.initUI()
                self.wt=WorkerThread() # This is the thread object
                self.wt.start()
                # Connect the signal from the thread to the finished method
                self.wt.signal_i.connect(self.slot_method)  ### 3) connect to the slot
                
            def initUI(self):
                cb  = QCheckBox("enable countdown")
                self.lcd = QLCDNumber(self)
                pro = QProgressBar(self)
                sld = QSlider(Qt.Horizontal, self)
        
                vbox = QVBoxLayout()
                vbox.addWidget(cb)
                vbox.addWidget(self.lcd)
                vbox.addWidget(pro)
                vbox.addWidget(sld)
                self.setLayout(vbox)
           
                self.setGeometry(300, 300, 250, 150)
                self.setWindowTitle('Signal and slot')
                self.show()
                
                sld.valueChanged.connect(pro.setValue)#link the slider to the progress bar
                #cb.stateChanged.connect(self.buttonchange)
                cb.stateChanged.connect(WorkerThread.run)
                
            def slot_method(self, i):   ### 4) this is the slot that receive the signal
                #print("i:",+i)
                self.lcd.display(i)
                
        #    def buttonchange(self, b):
        #        if b == 0:
        #            print ("non checked")
        #        else:
        #            print("checked")
        
        if __name__ == '__main__':
            app = QApplication(sys.argv)
            ex = Example()
            sys.exit(app.exec_())
        
        
        1 Reply Last reply
        0
        • S Offline
          S Offline
          SGaist
          Lifetime Qt Champion
          wrote on 11 Aug 2018, 20:22 last edited by
          #4

          Why are you trying to connect the checkbox to the run method ? That's not the goal of that method at all.

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

          W 1 Reply Last reply 11 Aug 2018, 20:30
          0
          • S SGaist
            11 Aug 2018, 20:22

            Why are you trying to connect the checkbox to the run method ? That's not the goal of that method at all.

            W Offline
            W Offline
            webgiorgio
            wrote on 11 Aug 2018, 20:30 last edited by
            #5

            @SGaist I want to use that check box to exit the while loop I will have in the Thread (reading data from the serial port, and sending it to the lcd).
            Otherwise when I close the GUI the Thread keeps running.

            1 Reply Last reply
            0
            • S Offline
              S Offline
              SGaist
              Lifetime Qt Champion
              wrote on 11 Aug 2018, 20:34 last edited by
              #6

              You can use QThread:: requestInterruption and in your run method isInterruptionRequested.

              But the check box is a wrong GUI idea, you should rather use a normal button.

              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
              • W Offline
                W Offline
                webgiorgio
                wrote on 12 Aug 2018, 07:35 last edited by webgiorgio 8 Dec 2018, 07:38
                #7
                This post is deleted!
                1 Reply Last reply
                0
                • W Offline
                  W Offline
                  webgiorgio
                  wrote on 12 Aug 2018, 07:53 last edited by webgiorgio 8 Dec 2018, 07:53
                  #8

                  The idea of the checkbox is to ebnable/disable the serial data read when the checkbox is selected/unselected.
                  It works with the method cbchange. Is this what you meant?

                  If I connect the interruption to the pushbutton, the gui hangs at boot

                  btn.clicked.connect(self.wt.requestInterruption()) #THIS HANGS
                  
                  #!/usr/bin/env python3
                  # -*- coding: utf-8 -*-
                  """
                  Created on Sat Aug 11 15:48:57 2018
                  
                  @author: gio
                  """
                  
                  
                  import sys
                  from PyQt5.QtCore import Qt
                  from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider, QProgressBar,
                      QVBoxLayout, QApplication, QCheckBox, QPushButton)
                  from PyQt5.QtCore import QThread, pyqtSignal
                  
                  import time
                  
                             
                  
                  class WorkerThread(QThread):
                      mysignal_i=pyqtSignal( int, name='Signal_i') ### 1) declare the signal
                      
                      def __init__(self, parent=None):
                          QThread.__init__(self)
                          #super(WorkerThread, self).__init__(parent)
                     
                      def run(self):
                          x = 10
                          for i in range(x):
                             time.sleep(1)
                             print(i) 
                             self.mysignal_i.emit(i)  ### 2) emitt the signal
                             if self.isInterruptionRequested():
                                 print ("exit loop")
                                 break
                             
                          
                          
                  class Example(QWidget):
                      def __init__(self):
                          super().__init__()
                          self.initUI()
                          self.wt=WorkerThread() # This is the thread object
                          #self.wt.start()
                          # Connect the signal from the thread to the slot_method
                          self.wt.mysignal_i.connect(self.slot_method)  ### 3) connect to the slot
                          
                      def initUI(self):
                          cb  = QCheckBox("enable countdown")
                          cb.setChecked(False)
                          self.lcd = QLCDNumber(self)
                          pro = QProgressBar(self)
                          sld = QSlider(Qt.Horizontal, self)
                          btn = QPushButton(self)
                          btn.setText('stop thread')
                  
                          vbox = QVBoxLayout()
                          vbox.addWidget(cb)
                          vbox.addWidget(btn)
                          vbox.addWidget(self.lcd)
                          vbox.addWidget(pro)
                          vbox.addWidget(sld)
                          self.setLayout(vbox)
                  
                  
                          self.setGeometry(300, 300, 300, 300)
                          self.setWindowTitle('Signal and slot')
                          self.show()
                          
                          sld.valueChanged.connect(pro.setValue)#link the slider to the progress bar
                          cb.stateChanged.connect(self.cbchange)
                          #cb.stateChanged.connect(WorkerThread.run)
                          
                          #btn.clicked.connect(self.wt.requestInterruption()) #THIS HANGS
                          
                      def slot_method(self, i):   ### 4) this is the slot that receive the signal
                          #print("i:",+i)
                          self.lcd.display(i)
                          
                      def cbchange(self, b):
                          if b == 0:
                              print ("non checked")
                              self.wt.requestInterruption()
                          else:
                              print("checked")
                              self.wt.start()
                  
                  if __name__ == '__main__':
                      app = QApplication(sys.argv)
                      ex = Example()
                      sys.exit(app.exec_())
                  
                  
                  JonBJ 1 Reply Last reply 12 Aug 2018, 11:12
                  0
                  • mrjjM Offline
                    mrjjM Offline
                    mrjj
                    Lifetime Qt Champion
                    wrote on 12 Aug 2018, 09:19 last edited by
                    #9

                    Hi
                    Does break in python do the same as return in c++ ?

                    void long_task() {
                         forever {
                            if ( QThread::currentThread()->isInterruptionRequested() ) {
                                return;
                            }
                        }
                    }
                    

                    If its break like in c++ , you only ask it to skip for loop but not bail out of run()
                    (i think/assume)

                    JonBJ 1 Reply Last reply 12 Aug 2018, 10:40
                    0
                    • mrjjM mrjj
                      12 Aug 2018, 09:19

                      Hi
                      Does break in python do the same as return in c++ ?

                      void long_task() {
                           forever {
                              if ( QThread::currentThread()->isInterruptionRequested() ) {
                                  return;
                              }
                          }
                      }
                      

                      If its break like in c++ , you only ask it to skip for loop but not bail out of run()
                      (i think/assume)

                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on 12 Aug 2018, 10:40 last edited by
                      #10

                      @mrjj
                      Python break == C++ break
                      Python return == C++ return
                      :)

                      mrjjM 1 Reply Last reply 12 Aug 2018, 11:07
                      2
                      • JonBJ JonB
                        12 Aug 2018, 10:40

                        @mrjj
                        Python break == C++ break
                        Python return == C++ return
                        :)

                        mrjjM Offline
                        mrjjM Offline
                        mrjj
                        Lifetime Qt Champion
                        wrote on 12 Aug 2018, 11:07 last edited by
                        #11

                        @JonB
                        Thanks so exactly the same.
                        so i guess it hangs as he only exit the for loop and run
                        repeats a moment later.

                        1 Reply Last reply
                        0
                        • W webgiorgio
                          12 Aug 2018, 07:53

                          The idea of the checkbox is to ebnable/disable the serial data read when the checkbox is selected/unselected.
                          It works with the method cbchange. Is this what you meant?

                          If I connect the interruption to the pushbutton, the gui hangs at boot

                          btn.clicked.connect(self.wt.requestInterruption()) #THIS HANGS
                          
                          #!/usr/bin/env python3
                          # -*- coding: utf-8 -*-
                          """
                          Created on Sat Aug 11 15:48:57 2018
                          
                          @author: gio
                          """
                          
                          
                          import sys
                          from PyQt5.QtCore import Qt
                          from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider, QProgressBar,
                              QVBoxLayout, QApplication, QCheckBox, QPushButton)
                          from PyQt5.QtCore import QThread, pyqtSignal
                          
                          import time
                          
                                     
                          
                          class WorkerThread(QThread):
                              mysignal_i=pyqtSignal( int, name='Signal_i') ### 1) declare the signal
                              
                              def __init__(self, parent=None):
                                  QThread.__init__(self)
                                  #super(WorkerThread, self).__init__(parent)
                             
                              def run(self):
                                  x = 10
                                  for i in range(x):
                                     time.sleep(1)
                                     print(i) 
                                     self.mysignal_i.emit(i)  ### 2) emitt the signal
                                     if self.isInterruptionRequested():
                                         print ("exit loop")
                                         break
                                     
                                  
                                  
                          class Example(QWidget):
                              def __init__(self):
                                  super().__init__()
                                  self.initUI()
                                  self.wt=WorkerThread() # This is the thread object
                                  #self.wt.start()
                                  # Connect the signal from the thread to the slot_method
                                  self.wt.mysignal_i.connect(self.slot_method)  ### 3) connect to the slot
                                  
                              def initUI(self):
                                  cb  = QCheckBox("enable countdown")
                                  cb.setChecked(False)
                                  self.lcd = QLCDNumber(self)
                                  pro = QProgressBar(self)
                                  sld = QSlider(Qt.Horizontal, self)
                                  btn = QPushButton(self)
                                  btn.setText('stop thread')
                          
                                  vbox = QVBoxLayout()
                                  vbox.addWidget(cb)
                                  vbox.addWidget(btn)
                                  vbox.addWidget(self.lcd)
                                  vbox.addWidget(pro)
                                  vbox.addWidget(sld)
                                  self.setLayout(vbox)
                          
                          
                                  self.setGeometry(300, 300, 300, 300)
                                  self.setWindowTitle('Signal and slot')
                                  self.show()
                                  
                                  sld.valueChanged.connect(pro.setValue)#link the slider to the progress bar
                                  cb.stateChanged.connect(self.cbchange)
                                  #cb.stateChanged.connect(WorkerThread.run)
                                  
                                  #btn.clicked.connect(self.wt.requestInterruption()) #THIS HANGS
                                  
                              def slot_method(self, i):   ### 4) this is the slot that receive the signal
                                  #print("i:",+i)
                                  self.lcd.display(i)
                                  
                              def cbchange(self, b):
                                  if b == 0:
                                      print ("non checked")
                                      self.wt.requestInterruption()
                                  else:
                                      print("checked")
                                      self.wt.start()
                          
                          if __name__ == '__main__':
                              app = QApplication(sys.argv)
                              ex = Example()
                              sys.exit(app.exec_())
                          
                          
                          JonBJ Offline
                          JonBJ Offline
                          JonB
                          wrote on 12 Aug 2018, 11:12 last edited by JonB 8 Dec 2018, 11:22
                          #12

                          @webgiorgio

                          btn.clicked.connect(self.wt.requestInterruption()) #THIS HANGS

                          You're misunderstanding how you're intended to use connect in PyQt. It's the same principle as in C++, just different syntax. The point is, you must connect to the function ("pointer"), you must not call the function in the argument to connect.

                          So all your PyQt connects need to look like:

                          btn.clicked.connect(self.wt.requestInterruption)
                          

                          Note that requestInterruption does not have a () at the end of it! Do you follow the vital difference? It's also the same principle as why you have to write btn.clicked.connect and not btn.clicked().connect.

                          1 Reply Last reply
                          3

                          1/12

                          11 Aug 2018, 15:26

                          • Login

                          • Login or register to search.
                          1 out of 12
                          • First post
                            1/12
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved