class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
loadUi('wind.ui', self)
self.startButton.clicked.connect(self.start_screen)
self.stopButton.clicked.connect(self.stop_screen)
self.screen_thread = Screenshot()
def start_screen(self):
self.screen_thread.start()
self.screen_thread.any_signal.connect(self.myfunction)
def stop_screen(self):
self.screen_thread.stop()
def myfunction(self,value):
vl = value
print(vl, threading.active_count())
class Screenshot(QThread):
any_signal = pyqtSignal(int)
def __init__(self, parent = None):
super(Screenshot, self).__init__(parent)
def run(self):
value = 1
print('process start')
print(threading.active_count())
print(threading.enumerate())
while(True):
value = 1
time.sleep(1)
self.any_signal.emit(value)
def stop(self):
print('process stop')
self.terminate()
print(self.isRunning())
def application():
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
if __name__ == "__main__":
application()
There are two start and stop buttons. when I run it for the first time, everything is ok, the value is printed once and incremented. then I press stop, everything stops. when I press start a second time, the result is printed twice. the third time three times, and so on. I thought that new threads were being added and entered a command to monitor threads. but only one thread is shown each time. where is the mistake?
CodePudding user response:
I thought that new threads were being added and entered a command to monitor threads. but only one thread is shown each time.
Only one thread is shown each time because you only create one thread: self.screen_thread = Screenshot()
Each time you click the start button it starts the thread (calling .start()
once a thread has started does nothing), and it connects the self.myfunction
slot to the any_signal
. Because you can connect the same slot multiple times to the same signal, it just gets called multiple times.
If you want multiple threads, then you will need to create them, and keep track of them. Something like this should do:
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
loadUi('wind.ui', self)
self.startButton.clicked.connect(self.start_screen)
self.stopButton.clicked.connect(self.stop_screen)
self.threads = []
def start_screen(self):
thread = Screenshot()
thread.any_signal.connect(self.myfunction)
thread.start()
self.threads.append(thread)
def stop_screen(self):
for thread in self.threads:
thread.stop()
self.threads = []
def myfunction(self,value):
vl = value
print(vl, threading.active_count())
class Screenshot(QThread):
any_signal = pyqtSignal(int)
def __init__(self, parent = None):
super(Screenshot, self).__init__(parent)
def run(self):
value = 1
print('process start')
print(threading.active_count())
print(threading.enumerate())
while(True):
value = 1
time.sleep(1)
self.any_signal.emit(value)
def stop(self):
print('process stop')
self.terminate()
print(self.isRunning())
def application():
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
if __name__ == "__main__":
application()
Note that the use of QThread.terminate
is discouraged:
Warning: This function is dangerous and its use is discouraged. The thread can be terminated at any point in its code path. Threads can be terminated while modifying data. There is no chance for the thread to clean up after itself, unlock any held mutexes, etc. In short, use this function only if absolutely necessary.
Instead, call QThread.requestInterruption
and regularly check for an interruption request within the thread with QThread.isInterruptionRequested
.