Getting unexpected results with QTimer.
-
I am hoping someone can help me with this. The code below controls an On screen display volume widget. A QTimer is started to wait 3 seconds before hiding the widget when a button is released. If a volume button is pressed again within those 3 seconds, the timer must be killed.
If I press a button repeatedly instead of held down, something weird happens. it's as if none of the timers have been killed; If I press a button, say 5 times fast, the widget hides 3 seconds after the first button press, and repeats the print message 4 times too. In other words, 5 different timers are running. It also has consequences for the widget, it starts flickering after three seconds. When the button is held down, the loop performs flawlessly and does not initiate a timer until the button is released - Even though the autorepeats simulates a button press plus a button release. I am a bit stumped, who can help me here?
Thank you.
The code in question:
class Carma(QtWidgets.QWidget): def __init__(self,init): super().__init__() if self.init == True: self.volstep = 1 # Volume step self.osd_delaytime = 3 # seconds self.mainvolume = 50 # startup volume self.volrate = 20 # volume change speed when using +- self.choice = -1 self.vol_delay_ms = 500 self.vol_interval_ms = 100 self.timer = QtCore.QTimer() self.init_ui() def setVolume(self): vol_int_ms = int((1/self.volrate)*1000) self.buttons_src[6].setStyleSheet("border-image: url(images/bezel-button.png)") self.buttons_src[6].setAutoRepeat(True) self.buttons_src[6].setAutoRepeatDelay(self.vol_delay_ms) self.buttons_src[6].setAutoRepeatInterval(vol_int_ms) self.buttons_src[6].pressed.connect(lambda: self.voldn()) self.buttons_src[6].clicked.connect(lambda: self.volhidetimer(2)) self.buttons_src[7].setStyleSheet("border-image: url(images/bezel-button.png)") self.buttons_src[7].setAutoRepeat(True) self.buttons_src[7].setAutoRepeatDelay(self.vol_delay_ms) self.buttons_src[7].setAutoRepeatInterval(vol_int_ms) self.buttons_src[7].pressed.connect(lambda: self.volup()) self.buttons_src[7].clicked.connect(lambda: self.volhidetimer(2)) self.init = False def voldn(self): self.timer.stop() print("voldn pressed", self.mainvolume) self.buttons_src[6].setStyleSheet("border-image: url(images/bezel-buttonp.png)") if self.osd_vol_widget.isHidden(): self.osd_vol_widget.show() if 1 <= self.mainvolume <= 100: self.mainvolume -= self.volstep self.osd_vol_bar.setValue(self.mainvolume) self.osd_vol_label.setText(str(self.mainvolume)) def volup(self): self.timer.stop() print("volup pressed", self.mainvolume) self.buttons_src[7].setStyleSheet("border-image: url(images/bezel-buttonp.png)") if self.osd_vol_widget.isHidden(): self.osd_vol_widget.show() if 0 <= self.mainvolume <= 99: self.mainvolume += self.volstep self.osd_vol_bar.setValue(self.mainvolume) self.osd_vol_label.setText(str(self.mainvolume)) def volhidetimer(self, delaytime): if not any(self.buttons_src[i].isDown() for i in (6, 7)): self.buttons_src[6].setStyleSheet("border-image: url(images/bezel-button.png)") self.timer.singleShot(delaytime * 1000, lambda: self.volhide()) print("Start timer volume hide") def volhide(self): if not any(self.buttons_src[i].isDown() for i in (6, 7)): self.osd_vol_widget.hide() print("Volume widget hidden")
-
Hi,
The singleShot method is a class function. You are creating a new independent single shot timer each time you call it.
-
Make set your timer as single shot and just restart it.