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. How to Use Multithreading
Forum Updated to NodeBB v4.3 + New Features

How to Use Multithreading

Scheduled Pinned Locked Moved Solved Qt for Python
15 Posts 3 Posters 2.4k 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.
  • V vidyul

    @jsulm so what I want to do is I press a button after pressing that button it should go to the method named suppose 'abc'.
    In method abc I need to perfrom continuous reading of data until stopped and at the same time update the display real time for the data that is coming.
    here is the sample code:
    #!/usr/bin/env python3

    import os, sys, time
    from PyQt5 import QtWidgets, QtCore
    from PyQt5.QtCore import QLibraryInfo, pyqtSignal, pyqtSlot, QUrl, QTimer, QTime, QDate, QThread
    from PyQt5.QtWidgets import QDialog, QApplication, QMainWindow
    from PyQt5.uic import loadUi
    from PyQt5.QtGui import QImage
    from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent

    os.environ["QT_QPA_PLATFORM_PLUGIN_PATH"] = QLibraryInfo.location(
    QLibraryInfo.PluginsPath
    )

    class Sample_UI(QDialog):
    def init(self):
    super(Sample_UI,self).init()
    loadUi('Sample_Update.ui',self)

        self.Reports_Table.setColumnWidth(0,250)
        
        self.label_4.setText('LOGIC_CONTROL')
        
        timer=QTimer(self)
        timer.timeout.connect(self.showTime)
        timer.start(1)
        self.Test_Button.clicked.connect(self.testing)
        self.Save_Button.clicked.connect(self.save_data)
    

    def logic(self):
    import logic_build_library
    self.abc=logic_build_library.class1()

        try:
            systat=self.abc.sys_status()
            if systat is not None:
                self.label_12.setStyleSheet('background-color: green; color: black;')
            else:
                self.label_12.setStyleSheet('background-color: red; color: black;')
        except Exception as e:
            self.label_12.setStyleSheet('background-color: red; color: black;')
    def showTime(self):
        currentTime = QTime.currentTime()
        today_date=QDate.currentDate()
        displayTxt = today_date.toString()+" "+currentTime.toString('hh:mm:ss')
        self.label_6.setText(displayTxt)
    def save_data(self):
        print('Data Saved!')
        login=Login()
        widget.setFixedWidth(360)
        widget.setFixedHeight(360)
        widget.addWidget(login)
        widget.setCurrentIndex(widget.currentIndex()+1)
    

    How can I continuously fetch data and display it at the same time?

    jsulmJ Offline
    jsulmJ Offline
    jsulm
    Lifetime Qt Champion
    wrote on last edited by
    #4

    @vidyul said in How to Use Multithreading:

    How can I continuously fetch data and display it at the same time?

    I have no idea how you fetch the data - you did not explain what camera and how you're accessing it. And regarding displaying: I already wrote that you can pass the data from the camera fetching thread to the UI thread using signals/slots.

    https://forum.qt.io/topic/113070/qt-code-of-conduct

    1 Reply Last reply
    0
    • V vidyul

      @jsulm so what I want to do is I press a button after pressing that button it should go to the method named suppose 'abc'.
      In method abc I need to perfrom continuous reading of data until stopped and at the same time update the display real time for the data that is coming.
      here is the sample code:
      #!/usr/bin/env python3

      import os, sys, time
      from PyQt5 import QtWidgets, QtCore
      from PyQt5.QtCore import QLibraryInfo, pyqtSignal, pyqtSlot, QUrl, QTimer, QTime, QDate, QThread
      from PyQt5.QtWidgets import QDialog, QApplication, QMainWindow
      from PyQt5.uic import loadUi
      from PyQt5.QtGui import QImage
      from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent

      os.environ["QT_QPA_PLATFORM_PLUGIN_PATH"] = QLibraryInfo.location(
      QLibraryInfo.PluginsPath
      )

      class Sample_UI(QDialog):
      def init(self):
      super(Sample_UI,self).init()
      loadUi('Sample_Update.ui',self)

          self.Reports_Table.setColumnWidth(0,250)
          
          self.label_4.setText('LOGIC_CONTROL')
          
          timer=QTimer(self)
          timer.timeout.connect(self.showTime)
          timer.start(1)
          self.Test_Button.clicked.connect(self.testing)
          self.Save_Button.clicked.connect(self.save_data)
      

      def logic(self):
      import logic_build_library
      self.abc=logic_build_library.class1()

          try:
              systat=self.abc.sys_status()
              if systat is not None:
                  self.label_12.setStyleSheet('background-color: green; color: black;')
              else:
                  self.label_12.setStyleSheet('background-color: red; color: black;')
          except Exception as e:
              self.label_12.setStyleSheet('background-color: red; color: black;')
      def showTime(self):
          currentTime = QTime.currentTime()
          today_date=QDate.currentDate()
          displayTxt = today_date.toString()+" "+currentTime.toString('hh:mm:ss')
          self.label_6.setText(displayTxt)
      def save_data(self):
          print('Data Saved!')
          login=Login()
          widget.setFixedWidth(360)
          widget.setFixedHeight(360)
          widget.addWidget(login)
          widget.setCurrentIndex(widget.currentIndex()+1)
      

      How can I continuously fetch data and display it at the same time?

      J.HilkJ Online
      J.HilkJ Online
      J.Hilk
      Moderators
      wrote on last edited by
      #5

      @vidyul let me chatgpt that for you:

      To continuously fetch data and update the display in real-time, you can use a separate thread to fetch the data and emit a signal every time new data is available. The main thread can then connect a slot to this signal to update the UI. Here’s a simplified example:

      class DataThread(QThread):
          data_signal = pyqtSignal(object)
      
          def run(self):
              while True:
                  data = self.fetch_data()  # replace with your data fetching logic
                  self.data_signal.emit(data)
                  time.sleep(1)  # sleep for a while to prevent high CPU usage
      
      class ATE_UI(QDialog):
          def __init__(self):
              super(ATE_UI,self).__init__()
              loadUi('ATE_Update.ui',self)
              
              self.Reports_Table.setColumnWidth(0,250)
              
              self.label_4.setText('Flight Mode: VTOL')
              
              timer=QTimer(self)
              timer.timeout.connect(self.showTime)
              timer.start(1)
              self.Test_Button.clicked.connect(self.start_fetching_data)
              self.Save_Button.clicked.connect(self.save_data)
      
              self.data_thread = DataThread()
              self.data_thread.data_signal.connect(self.update_display)
      
          def start_fetching_data(self):
              self.data_thread.start()
      
          def update_display(self, data):
              # update your display with the new data here
              pass
      
          # ... rest of your code ...
      
      

      In this example, pressing the Test_Button will start the DataThread, which fetches data in a loop until stopped. Every time new data is fetched, it emits a signal with the data, which is connected to the update_display slot in the main thread. This slot can then update the UI with the new data.

      Please replace self.fetch_data() with your actual data fetching logic and implement the update_display method to update your UI with the new data. Also, don’t forget to handle stopping the thread when necessary. You might want to add a stop button and connect it to a method that calls self.data_thread.terminate(). Be aware that terminating threads can be dangerous if not handled properly, so it’s better to have a mechanism in your thread to stop it gracefully. For example, you can use a QMutex and a flag to check whether the thread should stop or continue fetching data. If the flag is set, the thread can finish its current iteration and then stop itself by returning from the run method. This way, you can avoid abruptly stopping the thread and potentially leaving resources in an inconsistent state.

      Please note that this is a simplified example and might not cover all edge cases. Always make sure to handle exceptions and edge cases in your code to prevent crashes and ensure a smooth user experience. Also, keep in mind that updating the UI from a different thread is not safe, and you should always use signals and slots for communication between threads in Qt.


      Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


      Q: What's that?
      A: It's blue light.
      Q: What does it do?
      A: It turns blue.

      V 2 Replies Last reply
      2
      • J.HilkJ J.Hilk

        @vidyul let me chatgpt that for you:

        To continuously fetch data and update the display in real-time, you can use a separate thread to fetch the data and emit a signal every time new data is available. The main thread can then connect a slot to this signal to update the UI. Here’s a simplified example:

        class DataThread(QThread):
            data_signal = pyqtSignal(object)
        
            def run(self):
                while True:
                    data = self.fetch_data()  # replace with your data fetching logic
                    self.data_signal.emit(data)
                    time.sleep(1)  # sleep for a while to prevent high CPU usage
        
        class ATE_UI(QDialog):
            def __init__(self):
                super(ATE_UI,self).__init__()
                loadUi('ATE_Update.ui',self)
                
                self.Reports_Table.setColumnWidth(0,250)
                
                self.label_4.setText('Flight Mode: VTOL')
                
                timer=QTimer(self)
                timer.timeout.connect(self.showTime)
                timer.start(1)
                self.Test_Button.clicked.connect(self.start_fetching_data)
                self.Save_Button.clicked.connect(self.save_data)
        
                self.data_thread = DataThread()
                self.data_thread.data_signal.connect(self.update_display)
        
            def start_fetching_data(self):
                self.data_thread.start()
        
            def update_display(self, data):
                # update your display with the new data here
                pass
        
            # ... rest of your code ...
        
        

        In this example, pressing the Test_Button will start the DataThread, which fetches data in a loop until stopped. Every time new data is fetched, it emits a signal with the data, which is connected to the update_display slot in the main thread. This slot can then update the UI with the new data.

        Please replace self.fetch_data() with your actual data fetching logic and implement the update_display method to update your UI with the new data. Also, don’t forget to handle stopping the thread when necessary. You might want to add a stop button and connect it to a method that calls self.data_thread.terminate(). Be aware that terminating threads can be dangerous if not handled properly, so it’s better to have a mechanism in your thread to stop it gracefully. For example, you can use a QMutex and a flag to check whether the thread should stop or continue fetching data. If the flag is set, the thread can finish its current iteration and then stop itself by returning from the run method. This way, you can avoid abruptly stopping the thread and potentially leaving resources in an inconsistent state.

        Please note that this is a simplified example and might not cover all edge cases. Always make sure to handle exceptions and edge cases in your code to prevent crashes and ensure a smooth user experience. Also, keep in mind that updating the UI from a different thread is not safe, and you should always use signals and slots for communication between threads in Qt.

        V Offline
        V Offline
        vidyul
        wrote on last edited by
        #6

        @J-Hilk thank you for the help. I have run a sample code and it is running, I will update here as solved when everything works fine.

        1 Reply Last reply
        1
        • V vidyul has marked this topic as solved on
        • J.HilkJ J.Hilk

          @vidyul let me chatgpt that for you:

          To continuously fetch data and update the display in real-time, you can use a separate thread to fetch the data and emit a signal every time new data is available. The main thread can then connect a slot to this signal to update the UI. Here’s a simplified example:

          class DataThread(QThread):
              data_signal = pyqtSignal(object)
          
              def run(self):
                  while True:
                      data = self.fetch_data()  # replace with your data fetching logic
                      self.data_signal.emit(data)
                      time.sleep(1)  # sleep for a while to prevent high CPU usage
          
          class ATE_UI(QDialog):
              def __init__(self):
                  super(ATE_UI,self).__init__()
                  loadUi('ATE_Update.ui',self)
                  
                  self.Reports_Table.setColumnWidth(0,250)
                  
                  self.label_4.setText('Flight Mode: VTOL')
                  
                  timer=QTimer(self)
                  timer.timeout.connect(self.showTime)
                  timer.start(1)
                  self.Test_Button.clicked.connect(self.start_fetching_data)
                  self.Save_Button.clicked.connect(self.save_data)
          
                  self.data_thread = DataThread()
                  self.data_thread.data_signal.connect(self.update_display)
          
              def start_fetching_data(self):
                  self.data_thread.start()
          
              def update_display(self, data):
                  # update your display with the new data here
                  pass
          
              # ... rest of your code ...
          
          

          In this example, pressing the Test_Button will start the DataThread, which fetches data in a loop until stopped. Every time new data is fetched, it emits a signal with the data, which is connected to the update_display slot in the main thread. This slot can then update the UI with the new data.

          Please replace self.fetch_data() with your actual data fetching logic and implement the update_display method to update your UI with the new data. Also, don’t forget to handle stopping the thread when necessary. You might want to add a stop button and connect it to a method that calls self.data_thread.terminate(). Be aware that terminating threads can be dangerous if not handled properly, so it’s better to have a mechanism in your thread to stop it gracefully. For example, you can use a QMutex and a flag to check whether the thread should stop or continue fetching data. If the flag is set, the thread can finish its current iteration and then stop itself by returning from the run method. This way, you can avoid abruptly stopping the thread and potentially leaving resources in an inconsistent state.

          Please note that this is a simplified example and might not cover all edge cases. Always make sure to handle exceptions and edge cases in your code to prevent crashes and ensure a smooth user experience. Also, keep in mind that updating the UI from a different thread is not safe, and you should always use signals and slots for communication between threads in Qt.

          V Offline
          V Offline
          vidyul
          wrote on last edited by
          #7

          @J-Hilk I have marked it as correct answer. I just wanted to know it for my knowledge that Can I have more than 1 worker class inherited from Q Thread? And How can I achieve that? It can be useful for me in the future.

          jsulmJ 1 Reply Last reply
          0
          • V vidyul

            @J-Hilk I have marked it as correct answer. I just wanted to know it for my knowledge that Can I have more than 1 worker class inherited from Q Thread? And How can I achieve that? It can be useful for me in the future.

            jsulmJ Offline
            jsulmJ Offline
            jsulm
            Lifetime Qt Champion
            wrote on last edited by
            #8

            @vidyul said in How to Use Multithreading:

            Can I have more than 1 worker class inherited from Q Thread?

            Sure, each of the worker runs then in its own thread.
            "And How can I achieve that?" - in the same way you create one worker.

            https://forum.qt.io/topic/113070/qt-code-of-conduct

            V 1 Reply Last reply
            1
            • jsulmJ jsulm

              @vidyul said in How to Use Multithreading:

              Can I have more than 1 worker class inherited from Q Thread?

              Sure, each of the worker runs then in its own thread.
              "And How can I achieve that?" - in the same way you create one worker.

              V Offline
              V Offline
              vidyul
              wrote on last edited by vidyul
              #9

              @jsulm
              @J-Hilk
              Thank you for that info. I am currently facing an issue with the QThread you suggested.
              After I finish with my task I am clicking a button and then going back to login page, but in the background the qthread is still running and printing the output. How should I end that thread when pressed the stop button and again use it when I press the button to start the process.

              J.HilkJ 1 Reply Last reply
              0
              • V vidyul

                @jsulm
                @J-Hilk
                Thank you for that info. I am currently facing an issue with the QThread you suggested.
                After I finish with my task I am clicking a button and then going back to login page, but in the background the qthread is still running and printing the output. How should I end that thread when pressed the stop button and again use it when I press the button to start the process.

                J.HilkJ Online
                J.HilkJ Online
                J.Hilk
                Moderators
                wrote on last edited by
                #10

                @vidyul usually you call quit() on the thread. Doesn't necessarily work, depends on what you're doing inside the thread. If there's no event loop running, but something like an infinite while loop. You'll have to quit that first.


                Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                Q: What's that?
                A: It's blue light.
                Q: What does it do?
                A: It turns blue.

                V 1 Reply Last reply
                0
                • J.HilkJ J.Hilk

                  @vidyul usually you call quit() on the thread. Doesn't necessarily work, depends on what you're doing inside the thread. If there's no event loop running, but something like an infinite while loop. You'll have to quit that first.

                  V Offline
                  V Offline
                  vidyul
                  wrote on last edited by
                  #11

                  @J-Hilk Yes, so in the def run there is a while True running. Will I have to pass the button(s) as an object when I am creating an instance of the DataThread class?

                  Or I need to do something else?

                  J.HilkJ 1 Reply Last reply
                  0
                  • V vidyul

                    @J-Hilk Yes, so in the def run there is a while True running. Will I have to pass the button(s) as an object when I am creating an instance of the DataThread class?

                    Or I need to do something else?

                    J.HilkJ Online
                    J.HilkJ Online
                    J.Hilk
                    Moderators
                    wrote on last edited by
                    #12

                    @vidyul I'm not an expert in Python, but I assume there are equivalents to Atomics and or mutex? You need to check that variable every so often inside the loop and exit the loop when the condition is set.

                    Let me ask the AI to whip up an example.


                    Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                    Q: What's that?
                    A: It's blue light.
                    Q: What does it do?
                    A: It turns blue.

                    J.HilkJ V 2 Replies Last reply
                    0
                    • J.HilkJ J.Hilk

                      @vidyul I'm not an expert in Python, but I assume there are equivalents to Atomics and or mutex? You need to check that variable every so often inside the loop and exit the loop when the condition is set.

                      Let me ask the AI to whip up an example.

                      J.HilkJ Online
                      J.HilkJ Online
                      J.Hilk
                      Moderators
                      wrote on last edited by
                      #13

                      @J-Hilk here you go:

                      import sys
                      import time
                      from PyQt5.QtCore import Qt, QThread, QTimer, QObject, QMutex, pyqtSignal
                      from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget
                      
                      class Worker(QObject):
                          finished = pyqtSignal()
                      
                          def __init__(self, mutex):
                              super().__init__()
                              self.mutex = mutex
                              self.stop_flag = False
                      
                          def run_long_task(self):
                              while not self.stop_flag:
                                  # Simulate some work
                                  time.sleep(1)
                                  print("Worker thread: Doing some work...")
                      
                              self.finished.emit()
                      
                      class Window(QMainWindow):
                          def __init__(self):
                              super().__init__()
                              self.clicksCount = 0
                              self.setup_ui()
                      
                          def setup_ui(self):
                              self.setWindowTitle("Thread Example")
                              self.resize(300, 150)
                              self.centralWidget = QWidget()
                              self.setCentralWidget(self.centralWidget)
                      
                              # Create widgets
                              self.clicksLabel = QLabel("Counting: 0 clicks", self)
                              self.clicksLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                              self.countBtn = QPushButton("Click me!", self)
                              self.countBtn.clicked.connect(self.count_clicks)
                              self.longRunningBtn = QPushButton("Long-Running Task!", self)
                              self.longRunningBtn.clicked.connect(self.run_long_task)
                      
                              # Set layout
                              layout = QVBoxLayout()
                              layout.addWidget(self.clicksLabel)
                              layout.addWidget(self.countBtn)
                              layout.addStretch()
                              layout.addWidget(self.longRunningBtn)
                              self.centralWidget.setLayout(layout)
                      
                          def count_clicks(self):
                              self.clicksCount += 1
                              self.clicksLabel.setText(f"Counting: {self.clicksCount} clicks")
                      
                          def run_long_task(self):
                              mutex = QMutex()
                              worker = Worker(mutex)
                      
                              def stop_worker():
                                  with mutex:
                                      worker.stop_flag = True
                      
                              # Connect the worker's finished signal to stop the worker
                              worker.finished.connect(stop_worker)
                      
                              # Start the worker thread
                              thread = QThread()
                              worker.moveToThread(thread)
                              thread.started.connect(worker.run_long_task)
                              thread.start()
                      
                      if __name__ == "__main__":
                          app = QApplication(sys.argv)
                          win = Window()
                          win.show()
                          sys.exit(app.exec_())
                      
                      

                      Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                      Q: What's that?
                      A: It's blue light.
                      Q: What does it do?
                      A: It turns blue.

                      V 1 Reply Last reply
                      0
                      • J.HilkJ J.Hilk

                        @vidyul I'm not an expert in Python, but I assume there are equivalents to Atomics and or mutex? You need to check that variable every so often inside the loop and exit the loop when the condition is set.

                        Let me ask the AI to whip up an example.

                        V Offline
                        V Offline
                        vidyul
                        wrote on last edited by
                        #14
                        This post is deleted!
                        1 Reply Last reply
                        0
                        • J.HilkJ J.Hilk

                          @J-Hilk here you go:

                          import sys
                          import time
                          from PyQt5.QtCore import Qt, QThread, QTimer, QObject, QMutex, pyqtSignal
                          from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget
                          
                          class Worker(QObject):
                              finished = pyqtSignal()
                          
                              def __init__(self, mutex):
                                  super().__init__()
                                  self.mutex = mutex
                                  self.stop_flag = False
                          
                              def run_long_task(self):
                                  while not self.stop_flag:
                                      # Simulate some work
                                      time.sleep(1)
                                      print("Worker thread: Doing some work...")
                          
                                  self.finished.emit()
                          
                          class Window(QMainWindow):
                              def __init__(self):
                                  super().__init__()
                                  self.clicksCount = 0
                                  self.setup_ui()
                          
                              def setup_ui(self):
                                  self.setWindowTitle("Thread Example")
                                  self.resize(300, 150)
                                  self.centralWidget = QWidget()
                                  self.setCentralWidget(self.centralWidget)
                          
                                  # Create widgets
                                  self.clicksLabel = QLabel("Counting: 0 clicks", self)
                                  self.clicksLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                                  self.countBtn = QPushButton("Click me!", self)
                                  self.countBtn.clicked.connect(self.count_clicks)
                                  self.longRunningBtn = QPushButton("Long-Running Task!", self)
                                  self.longRunningBtn.clicked.connect(self.run_long_task)
                          
                                  # Set layout
                                  layout = QVBoxLayout()
                                  layout.addWidget(self.clicksLabel)
                                  layout.addWidget(self.countBtn)
                                  layout.addStretch()
                                  layout.addWidget(self.longRunningBtn)
                                  self.centralWidget.setLayout(layout)
                          
                              def count_clicks(self):
                                  self.clicksCount += 1
                                  self.clicksLabel.setText(f"Counting: {self.clicksCount} clicks")
                          
                              def run_long_task(self):
                                  mutex = QMutex()
                                  worker = Worker(mutex)
                          
                                  def stop_worker():
                                      with mutex:
                                          worker.stop_flag = True
                          
                                  # Connect the worker's finished signal to stop the worker
                                  worker.finished.connect(stop_worker)
                          
                                  # Start the worker thread
                                  thread = QThread()
                                  worker.moveToThread(thread)
                                  thread.started.connect(worker.run_long_task)
                                  thread.start()
                          
                          if __name__ == "__main__":
                              app = QApplication(sys.argv)
                              win = Window()
                              win.show()
                              sys.exit(app.exec_())
                          
                          
                          V Offline
                          V Offline
                          vidyul
                          wrote on last edited by vidyul
                          #15

                          @J-Hilk
                          So the current main.py file is:
                          sample.png
                          Now I want to know where should I implement this part:
                          def run_long_task(self):
                          mutex = QMutex()
                          worker = Worker(mutex)

                              def stop_worker():
                                  with mutex:
                                      worker.stop_flag = True
                          
                              # Connect the worker's finished signal to stop the worker
                              worker.finished.connect(stop_worker)
                          

                          because I tried but it was not working. It prompt to force close the UI.
                          @J-Hilk

                          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