Иногда при разработке приложений необходимо отложить действие на определенный срок. При этом зачастую отслеживать исполнение нет необходимости. Рассмотрим пример отложенного действия на PyQt5 при помощи QTimer
, для этого создадим простейший таймер обратного отсчёта без возможности прерывания.
Для этого добавляем на интерфейс приложения QLCDNumber
- на нем мы будем отображать текущее значение, QSlider
- при помощи него мы будем устанавливать желаемое значение и кнопку QPushButton
для запуска таймера.
Полный листинг программы приведен ниже (с расстановкой элементов и подключением слотов к сигналам), а сейчас я опишу суть:
- По нажатию кнопки
Start
отрабатывается методstart_btn_clicked
. Для того, чтобы случайно не изменить значение и не нарушить выполнение текущего отсчёта, мы отключаем слайдер и кнопку старта (self.toggle_btns(False)
), а затем запускаем сам таймер методомtick_timer
. - Внутри метода
tick_timer
мы получаем текущее значение на экранеlcd_value = self.lcd.value()
и проверяем, достигло ли оно нуля. Если значение больше, то отнимаем от него единицу (у нас отсчёт идет в секундах) и создаем экземплярQTimer
, на котором сразу вызываем методsingleShot
:QTimer().singleShot(1000, self.tick_timer)
. Он создаёт фоновый процесс с обратным отсчётом. Первое значение передаем время, через которое таймер должен сработать (в миллисекундах), а второй параметр - функция, которая должна быть вызвана по окончанию. Передаём тудаtick_timer
, чтобы достичь нуля на дисплее - Как только мы достигли нуля на дисплее, включаем кнопки обратно
self.toggle_btns()
, а на дисплей устанавливаем значение со слайдера (то значение, с которого мы начали отсчёт в прошлый раз)self.lcd.display(self.slider.value())
Вот и всё, таким образом мы сделали самый простой таймер на PyQt5.
import sys
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtWidgets import QWidget, QApplication, \
QLCDNumber, QSlider, QVBoxLayout, QHBoxLayout, QPushButton
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.lcd = QLCDNumber(self)
# Устанавливаем значение по умолчанию на дисплей
self.lcd.display(1)
self.slider = QSlider(Qt.Horizontal, self)
# Устанавливаем минимальное и максимальное значение
self.slider.setMinimum(1)
self.slider.setMaximum(90)
self.slider.valueChanged.connect(self.lcd.display)
self.start_btn = QPushButton('Start', self)
self.start_btn.clicked.connect(self.start_btn_clicked)
self.toggle_btns()
hbox = QHBoxLayout()
hbox.addWidget(self.slider)
hbox.addWidget(self.start_btn)
vbox = QVBoxLayout()
vbox.addWidget(self.lcd)
vbox.addLayout(hbox)
self.setLayout(vbox)
self.setWindowTitle('Timer PyQt5')
self.resize(400, 300)
def toggle_btns(self, value=True):
self.slider.setEnabled(value)
self.start_btn.setEnabled(value)
def start_btn_clicked(self):
# Отключаем слайдер и кнопку старта
self.toggle_btns(False)
# запускаем отсчет
self.tick_timer()
def tick_timer(self):
# Получаем значение на LCD виджете
lcd_value = self.lcd.value()
if lcd_value > 0:
# Устанавливаем значение на 1 меньше
self.lcd.display(lcd_value - 1)
# Засекаем таймер - значение в милисекундах
# метод singleShot создает поток в фоне, отменить его нельзя
QTimer().singleShot(1000, self.tick_timer)
else:
# Значение дисплея стало 0
# Включаем элементы интерфейса обратно
self.toggle_btns()
# Устанавливаем на дисплей выбранную на слайдере настройку
self.lcd.display(self.slider.value())
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())