Не используйте sleep в GUI, потому что вы можете заморозить GUI.С другой стороны, использование потока является слишком сложным для этого вопроса, в графическом интерфейсе использование потока оправдано, только если задача тяжелая, но увеличение пары данных каждую секунду не является тяжелой задачей.
Вместо этого вы должны использовать QTimer для выполнения повторяющихся задач и QTime для получения истекшего времени.
Для логики должен быть реализован конечный автомат, в этом случае это будет StopWatch, который будет излучать необходимые сигналы для уведомленияизменения в графическом интерфейсе.
from PyQt5 import QtCore, QtWidgets
from stpw_ui import Ui_MainWindow
class State:
STOPPED = 0
PAUSE = 1
RUNNING = 1 << 1
class StopWatch(QtCore.QObject, State):
State = State
QtCore.Q_ENUMS(State)
secondChanged = QtCore.pyqtSignal(int)
minuteChanged = QtCore.pyqtSignal(int)
stateChanged = QtCore.pyqtSignal(State)
def __init__(self, parent=None):
super(StopWatch, self).__init__(parent)
self._current_state = State.STOPPED
self._time = QtCore.QTime()
self._timer = QtCore.QTimer(self, interval=100, timeout=self.on_timeout)
self._delta = 0
self._seconds = 0
self._minutes = 0
def setCurrentState(self, state):
self._current_state = state
self.stateChanged.emit(state)
@QtCore.pyqtSlot()
def start(self):
self._delta = 0
self._timer.start()
self._time.start()
self.setCurrentState(State.RUNNING)
@QtCore.pyqtSlot()
def stop(self):
if self._current_state != State.STOPPED:
self._timer.stop()
self.setCurrentState(State.STOPPED)
@QtCore.pyqtSlot()
def pause(self):
if self._current_state == State.RUNNING:
self._timer.stop()
self.setCurrentState(State.PAUSE)
self._delta += self._time.elapsed()
@QtCore.pyqtSlot()
def resume(self):
if self._current_state == State.PAUSE:
self._timer.start()
self._time = QtCore.QTime()
self._time.start()
self.setCurrentState(State.RUNNING)
@QtCore.pyqtSlot()
def on_timeout(self):
t = QtCore.QTime.fromMSecsSinceStartOfDay(self._delta + self._time.elapsed())
s, m = t.second(), t.minute()
if self._seconds != s:
self._seconds = s
self.secondChanged.emit(s)
if self._minutes != m:
self._minutes = m
self.minuteChanged.emit(m)
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self._stop_watch = StopWatch(self)
self.start.clicked.connect(self._stop_watch.start)
self.pause.clicked.connect(self._stop_watch.pause)
self.stop.clicked.connect(self._stop_watch.stop)
self.resume.clicked.connect(self._stop_watch.resume)
self._stop_watch.secondChanged.connect(self.seconds.display)
self._stop_watch.minuteChanged.connect(self.minutes.display)
self._stop_watch.stateChanged.connect(self.on_stateChanged)
@QtCore.pyqtSlot(StopWatch.State)
def on_stateChanged(self, state):
if state == StopWatch.RUNNING:
self.stacked_buttons.setCurrentIndex(1)
elif state == StopWatch.PAUSE:
self.stacked_buttons.setCurrentIndex(2)
elif state == StopWatch.STOPPED:
self.stacked_buttons.setCurrentIndex(0)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())