Настроить потоки в pyqt5
Мне нужно, чтобы при нажатии кнопки Stop, потоки останавливали работу, и интерфейс не залипал, а после я мог нажать Start, чтобы потоки продолжили работать с места где остановились.
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
"""Класс инициализирующий первый поток"""
class first_thread(QtCore.QThread):
def __init__(self, mainwindow, parent = None):
super().__init__()
self.mainwindow = mainwindow
def run(self):
self.count = 0
while self.count < 100:
self.count += 1
self.mainwindow.first_lcd.display(self.count)
QtCore.QThread.msleep(100)
"""Класс инициализирующий второй поток"""
class second_thread(QtCore.QThread):
def __init__(self, mainwindow, parent = None):
super().__init__()
self.mainwindow = mainwindow
def run(self):
self.count = 0
while self.count < 100:
self.count += 1
self.mainwindow.second_lcd.display(self.count)
QtCore.QThread.msleep(100)
"""Класс, который создает окно и распологает на нем виджеты"""
class MyWindow(QtWidgets.QMainWindow):
def __init__(self, parent = None):
super().__init__()
#Объявляем центральный виджет, на нем будут располагаться остальные
self.resize(810, 310)
self.centralwidget = QtWidgets.QWidget()
#Располагаем два LCD Number
self.first_lcd = QtWidgets.QLCDNumber(self.centralwidget)
self.first_lcd.setGeometry(QtCore.QRect(10, 70, 380, 80))
self.second_lcd = QtWidgets.QLCDNumber(self.centralwidget)
self.second_lcd.setGeometry(QtCore.QRect(420, 70, 370, 80))
#Распологаем кнопки start и stop
self.start_btn = QtWidgets.QPushButton(self.centralwidget)
self.start_btn.setGeometry(QtCore.QRect(270, 240, 110, 50))
self.start_btn.setText("Start")
self.stop_btn = QtWidgets.QPushButton(self.centralwidget)
self.stop_btn.setGeometry(QtCore.QRect(410, 240, 110, 50))
self.stop_btn.setText("Stop")
#Располагаем два текстовых указателя(label)
font = QtGui.QFont()
font.setPointSize(16)
self.first_thr_lbl = QtWidgets.QLabel(self.centralwidget)
self.first_thr_lbl.setGeometry(QtCore.QRect(130, 20, 160, 30))
self.first_thr_lbl.setFont(font)
self.first_thr_lbl.setText("Первый поток")
self.second_thr_lbl = QtWidgets.QLabel(self.centralwidget)
self.second_thr_lbl.setGeometry(QtCore.QRect(550, 20, 150, 30))
self.second_thr_lbl.setFont(font)
self.second_thr_lbl.setText("Второй поток")
#Располагаем центральный виджет на окно
self.setCentralWidget(self.centralwidget)
#Объявляем потоки
self.first_thread = first_thread(mainwindow = self)
self.second_thread = second_thread(mainwindow = self)
self.start_btn.clicked.connect(self.launch_threads)#Кнопка подает сигнал в функцию, запускающую потоки
self.stop_btn.clicked.connect(self.stop_threads)#Кнопка подает сигнал в функцию, останавливающую потоки
#Функция, запускающая потоки
def launch_threads(self):
self.first_thread.start()
self.second_thread.start()
#Функция, останавливающая потоки
def stop_threads(self):
self.first_thread.usleep()
self.second_thread.usleep()
"""Запуск скрипта"""
app = QtWidgets.QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
Ответы (1 шт):
Автор решения: S. Nick
→ Ссылка
Нельзя использовать объекты основного потока в дополнительных потоках, это не безопасно! Надо использовать сигналы и слоты, примерно так:
import sys
from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.Qt import *
"""Класс инициализирующий первый поток"""
class first_thread(QtCore.QThread):
first_thread_signal = QtCore.pyqtSignal(int)
first_thread_finish = QtCore.pyqtSignal()
def __init__(self): #, mainwindow, parent = None):
super().__init__()
# self.mainwindow = mainwindow
self.count = 0
self.flag = True
def run(self):
# self.count = 0
while self.count < 100 and self.flag:
self.count += 1
# self.mainwindow.first_lcd.display(self.count)
self.first_thread_signal.emit(self.count)
self.msleep(100)
self.first_thread_finish.emit()
"""Класс инициализирующий второй поток"""
class second_thread(QtCore.QThread):
second_thread_signal = QtCore.pyqtSignal(int)
second_thread_finish = QtCore.pyqtSignal()
def __init__(self):
super().__init__()
self.count = 0
self.flag = True
def run(self):
while self.count < 100 and self.flag:
self.count += 1
self.second_thread_signal.emit(self.count)
self.msleep(100)
self.second_thread_finish.emit()
"""Класс, который создает окно и распологает на нем виджеты"""
class MyWindow(QtWidgets.QMainWindow):
def __init__(self, parent = None):
super().__init__()
#Объявляем центральный виджет, на нем будут располагаться остальные
self.resize(810, 310)
self.centralwidget = QtWidgets.QWidget()
#Располагаем два LCD Number
self.first_lcd = QtWidgets.QLCDNumber(self.centralwidget)
self.first_lcd.setGeometry(QtCore.QRect(10, 70, 380, 80))
self.second_lcd = QtWidgets.QLCDNumber(self.centralwidget)
self.second_lcd.setGeometry(QtCore.QRect(420, 70, 370, 80))
#Распологаем кнопки start и stop
self.start_btn = QtWidgets.QPushButton(self.centralwidget)
self.start_btn.setGeometry(QtCore.QRect(270, 240, 110, 50))
self.start_btn.setText("Start")
self.stop_btn = QtWidgets.QPushButton(self.centralwidget)
self.stop_btn.setGeometry(QtCore.QRect(410, 240, 110, 50))
self.stop_btn.setText("Stop")
#Располагаем два текстовых указателя(label)
font = QtGui.QFont()
font.setPointSize(16)
self.first_thr_lbl = QtWidgets.QLabel(self.centralwidget)
self.first_thr_lbl.setGeometry(QtCore.QRect(130, 20, 160, 30))
self.first_thr_lbl.setFont(font)
self.first_thr_lbl.setText("Первый поток")
self.second_thr_lbl = QtWidgets.QLabel(self.centralwidget)
self.second_thr_lbl.setGeometry(QtCore.QRect(550, 20, 150, 30))
self.second_thr_lbl.setFont(font)
self.second_thr_lbl.setText("Второй поток")
#Располагаем центральный виджет на окно
self.setCentralWidget(self.centralwidget)
#Объявляем потоки
self.first_thread = first_thread() #(mainwindow = self)
self.first_thread.first_thread_signal.connect(self.first_lcd_display)
self.first_thread.first_thread_finish.connect(self.first_finish)
self.second_thread = second_thread() #(mainwindow = self)
self.second_thread.second_thread_signal.connect(self.second_lcd_display)
self.first_thread.first_thread_finish.connect(self.second_finish)
self.start_btn.clicked.connect(self.launch_threads)#Кнопка подает сигнал в функцию, запускающую потоки
self.stop_btn.clicked.connect(self.stop_threads)#Кнопка подает сигнал в функцию, останавливающую потоки
def first_lcd_display(self, value):
self.first_lcd.display(value)
def second_lcd_display(self, value):
self.second_lcd.display(value)
def first_finish(self):
if self.first_thread.count == 100: self.first_thread.count = 0
def second_finish(self):
if self.second_thread.count == 100: self.second_thread.count = 0
#Функция, запускающая потоки
def launch_threads(self):
self.first_thread.flag = True
self.second_thread.flag = True
self.first_thread.start()
self.second_thread.start()
#Функция, останавливающая потоки
def stop_threads(self):
self.first_thread.flag = False
self.second_thread.flag = False
# self.first_thread.usleep()
# self.second_thread.usleep()
if __name__ == '__main__':
"""Запуск скрипта"""
app = QtWidgets.QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
