Ответ вроде как нашел, но немного не могу додуматься. Знатоки поточности "thread" и PyQt выручайте новичка.
Суть: Есть программа, таймер обратного отсчета. Сначала кнопками "Up" и "Down" выбираем время, жмем старт и должен пойти отсчет в
label. Так же кнопка "Start" становиться кнопкой "Стоп". При её нажатии отсчет прекращается и всё возвращается в начальное положение. После окончания таймера в данном случае выполняется "print("END")"
Характер проблемы: При нажатии кнопок "Up" и "Down", label меняется. Но при нажатии "Start" интерфейс программы зависает, однако сам код продолжает выполняться.
from PyQt5 import QtCore, QtGui, QtWidgets
import os
from time import sleep
import threading
global hours
global minutes
global seconds
hours = "00"
minutes = "00"
seconds = "00"
global flag
flag = "green"
def sleep_timer():
global hours
global minutes
global seconds
if int(minutes) > 0:
minutes = int(minutes) - 1
seconds = "59"
flag_timer = True
while flag_timer:
while int(hours) >= 0:
while int(minutes) >= 0:
while int(seconds) > 0:
if int(minutes) < 10:
minutes = "0" + str(minutes)
if int(seconds) < 10:
seconds = "0" + str(seconds)
all_numbers = str(hours) + ":" + str(minutes) + ":" + str(seconds)
self.label.setText(all_numbers)
print(all_numbers)
minutes = int(minutes)
seconds = int(seconds)
seconds = int(seconds) - 1
QtCore.QThread.sleep(1)
minutes = int(minutes) - 1
seconds = 59
if int(hours) != 0:
hours = int(hours) - 1
minutes = 59
else:
hours = int(hours) - 1
flag_timer = False
print("END")
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(230, 185)
MainWindow.setStyleSheet("background-color: rgb(26, 74, 90);")
MainWindow.setWindowIcon(QtGui.QIcon("time.png"))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(0, 40, 230, 60))
font = QtGui.QFont()
font.setPointSize(32)
font.setBold(True)
font.setWeight(75)
self.label.setFont(font)
self.label.setStyleSheet("color: rgb(20, 141, 141);")
self.label.setAlignment(QtCore.Qt.AlignCenter)
self.label.setObjectName("label")
self.btn_up_m = QtWidgets.QPushButton(self.centralwidget)
self.btn_up_m.setGeometry(QtCore.QRect(90, 20, 51, 23))
self.btn_up_m.setStyleSheet("background-color: rgb(20, 141, 141);border: 0;border-radius: 5px;color: #c1e1a7;font: bold;")
self.btn_up_m.setObjectName("btn_up_m")
self.btn_up_h = QtWidgets.QPushButton(self.centralwidget)
self.btn_up_h.setGeometry(QtCore.QRect(20, 20, 51, 23))
self.btn_up_h.setStyleSheet("background-color: rgb(20, 141, 141);border: 0;border-radius: 5px;color: #c1e1a7;font: bold;")
self.btn_up_h.setObjectName("btn_up_h")
self.btn_down_h = QtWidgets.QPushButton(self.centralwidget)
self.btn_down_h.setGeometry(QtCore.QRect(20, 100, 51, 23))
self.btn_down_h.setStyleSheet("background-color: rgb(20, 141, 141);border: 0;border-radius: 5px;color: #c1e1a7;font: bold;")
self.btn_down_h.setObjectName("btn_down_h")
self.btn_down_m = QtWidgets.QPushButton(self.centralwidget)
self.btn_down_m.setGeometry(QtCore.QRect(90, 100, 51, 23))
self.btn_down_m.setStyleSheet("background-color: rgb(20, 141, 141);border: 0;border-radius: 5px;color: #c1e1a7;font: bold;")
self.btn_down_m.setObjectName("btn_down_m")
self.btn_start = QtWidgets.QPushButton(self.centralwidget)
self.btn_start.setGeometry(QtCore.QRect(30, 130, 171, 23))
self.btn_start.setStyleSheet("background-color: #5EE88D;border: 0;border-radius: 5px;color: rgb(26, 74, 90);font-size: 16px;font: bold;")
# Red = #E8635E
# Green = #5EE88D
self.btn_start.setObjectName("btn_start")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 230, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
self.add_functions()
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Sleep timer"))
self.label.setText(_translate("MainWindow", "00:00:00"))
self.btn_up_m.setText(_translate("MainWindow", "UP"))
self.btn_up_h.setText(_translate("MainWindow", "UP"))
self.btn_down_h.setText(_translate("MainWindow", "DOWN"))
self.btn_down_m.setText(_translate("MainWindow", "DOWN"))
self.btn_start.setText(_translate("MainWindow", "START"))
def add_functions(self):
self.btn_up_h.clicked.connect(lambda: self.add_number("h", "up"))
self.btn_down_h.clicked.connect(lambda: self.add_number("h", "down"))
self.btn_up_m.clicked.connect(lambda: self.add_number("m", "up"))
self.btn_down_m.clicked.connect(lambda: self.add_number("m", "down"))
self.btn_start.clicked.connect(lambda: self.start(flag))
def add_number(self, first, second):
global hours
global minutes
global seconds
if first == "h":
if second == "up":
if int(hours) == 12:
hours = "00"
else:
hours = int(hours) + 1
if int(hours) < 10:
hours = "0" + str(hours)
if second == "down":
if int(hours) == 0:
hours = "12"
else:
hours = int(hours) - 1
if int(hours) < 10:
hours = "0" + str(hours)
if first == "m":
if second == "up":
if int(minutes) == 59:
minutes = "00"
else:
minutes = int(minutes) + 1
if int(minutes) < 10:
minutes = "0" + str(minutes)
if second == "down":
if int(minutes) == 0:
minutes = "59"
else:
minutes = int(minutes) - 1
if int(minutes) < 10:
minutes = "0" + str(minutes)
all_numbers = str(hours) + ":" + str(minutes) + ":" + str(seconds)
self.label.setText(all_numbers)
# Функция для кнопки START
def start(self, flag_1):
global hours
global minutes
global seconds
global flag
if flag_1 == "green":
flag = "red"
self.btn_start.setStyleSheet("background-color: #E8635E;border: 0;border-radius: 5px;color: rgb(26, 74, 90);font-size: 16px;font: bold;")
self.btn_start.setText("STOP")
self.btn_up_h.setVisible(False)
self.btn_down_h.setVisible(False)
self.btn_up_m.setVisible(False)
self.btn_down_m.setVisible(False)
#t = QtCore.QThread.thread(target=sleep_timer(self), args=())
t.start()
#sleep_timer(self)
else:
flag = "green"
self.btn_start.setStyleSheet("background-color: #5EE88D;border: 0;border-radius: 5px;color: rgb(26, 74, 90);font-size: 16px;font: bold;")
self.btn_start.setText("START")
hours = "00"
minutes = "00"
seconds = "00"
all_numbers = str(hours) + ":" + str(minutes) + ":" + str(seconds)
self.label.setText(all_numbers)
self.btn_up_h.setVisible(True)
self.btn_down_h.setVisible(True)
self.btn_up_m.setVisible(True)
self.btn_down_m.setVisible(True)
t = threading.Thread(target = sleep_timer(), args=())
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
#global MainWindow
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Начитался, мол, надо писать многопоточность, для меня PyQt то что то новое, а тут многопоточность... Ну нашел какой-то код. Попробовал из него взять кусочек. Работает, но вот какая ошибка: Я не могу понять "ветку"
label, когда она находиться ВНЕ класса. (Строка 32) Когда внутри класса я обращаюсь просто, через
self.
Помогите сделать это рабочим. Спасибо!
P.S. - Прошу прощения если написал вопрос некорректно или непонятно. Первый раз сюда обращаюсь. Не ругайте.
P.S.2 - Если есть какие ни будь предложения по "оптимизации" и лучшей читаемости кода, я Вас очень внимательно слушаю. Возможно что-то, где то, можно было организовать проще и правильней. Еще раз, спасибо!
P.S.3 - Для проверки кода, закомментируйте следующие строки:
173 t.start()
190 t = threading.Thread(target = sleep_timer(), args=())