How do I start my function every 5 minutes and 20 seconds? I used:
self.timer = QtCore.QTimer(self)
self.timer.timeout.connect(self.updateplot)
self.timer.start(310000)
But I'd like to set it by the time of my PC - so if I start the program at 3:23, the update track is at 3:25:20, 3:30:20 etc.
Two timers are needed for this: a single-shot to get to the starting point, which then triggers a second timer which times-out every 5 minutes (at the 20th second). The starting point can be calculated with QDateTime.msecsTo, so the code would look something like this:
mins = 5
secs = 20
self.timer = QtCore.QTimer(self)
self.timer.timeout.connect(self.updateplot)
self.timer.setInterval(mins * 60 * 1000)
def start_point():
self.timer.timeout.emit()
self.timer.start()
d1 = QtCore.QDateTime.currentDateTimeUtc()
d2 = QtCore.QDateTime(d1)
t1 = d1.time()
d2.setTime(QtCore.QTime(t1.hour(), t1.minute(), secs))
if t1.second() > secs:
d2 = d2.addSecs((mins - t1.minute() % mins) * 60)
QtCore.QTimer.singleShot(d1.msecsTo(d2), start_point)
Note that the accuracy of this depends on the system clock, and there will also be a fraction of a second lag whilst the start point is calculated - so don't expect it to stay perfectly in sync with the network time. If you need it to run for a long time, you could check the current time in updateplot
and restart the timer if it starts to drift beyond a certain threshold.
UPDATE:
Here's a demo that uses the above approach:
import sys
from PyQt5 import QtCore, QtWidgets
class Window(QtWidgets.QWidget):
def __init__(self):
super(Window, self).__init__()
self.spinMins = QtWidgets.QSpinBox()
self.spinMins.setRange(0, 59)
self.spinMins.setValue(1)
self.spinSecs = QtWidgets.QSpinBox()
self.spinSecs.setRange(0, 59)
self.spinSecs.setValue(5)
self.button = QtWidgets.QPushButton('Start')
self.button.clicked.connect(self.resetTimer)
self.edit = QtWidgets.QTextEdit()
self.edit.setReadOnly(True)
layout = QtWidgets.QGridLayout(self)
layout.addWidget(self.edit, 0, 0, 1, 3)
layout.addWidget(self.spinMins, 1, 0)
layout.addWidget(self.spinSecs, 1, 1)
layout.addWidget(self.button, 1, 2)
self.mainTimer = QtCore.QTimer(self)
self.mainTimer.timeout.connect(self.updateplot)
self.startTimer = QtCore.QTimer(self)
self.startTimer.setSingleShot(True)
def start_point():
self.mainTimer.timeout.emit()
self.mainTimer.start()
self.startTimer.timeout.connect(start_point)
self.resetTimer()
def resetTimer(self):
self.mainTimer.stop()
self.startTimer.stop()
mins = self.spinMins.value()
secs = self.spinSecs.value()
self.edit.append('restarting timer... (%dm %ds)' % (mins, secs))
self.mainTimer.setInterval(mins * 60 * 1000)
d1 = QtCore.QDateTime.currentDateTimeUtc()
d2 = QtCore.QDateTime(d1)
t1 = d1.time()
d2.setTime(QtCore.QTime(t1.hour(), t1.minute(), secs))
if t1.second() > secs:
d2 = d2.addSecs((mins - t1.minute() % mins) * 60)
self.startTimer.start(d1.msecsTo(d2))
def updateplot(self, t=None):
t = QtCore.QTime.currentTime()
self.edit.append('timeout: %s' % t.toString('HH:mm:ss.zzz'))
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.setWindowTitle('Timer Test')
window.setGeometry(600, 100, 300, 200)
window.show()
sys.exit(app.exec_())