Indigo
Indigo

Reputation: 962

Repeat function call while button is pressed PyQt5

I started with some code like this which connects a function to a GUI button.

    def on_click():
        call_other_funct()
        time.sleep(1)
    button = QPushButton('Do the thing', self)
    button.pressed.connect(on_click)

The problem is I need to repeatedly call on_click() every second for the duration of the mouse being held down on the button. I've searched quite a bit but haven't found a solution using PyQt.

I've been trying to fix this using a timer interval

    def on_release():
        self.timer.stop()

    def on_click():
        self.timer.start(1000)
        self.timer.timeout.connect(on_click())
        print('click')
    button.pressed.connect(on_click)
    button.released.connect(on_release)

This sort of works, but for some reason there seem to be and exponential number of on_click() calls happening. (on the first call, "click" prints once, then twice, then 4 times, then 8 etc). Is there a way to make this work correctly so each call only calls itself again once?

Or is there an all together better way to be doing this?

Upvotes: 0

Views: 3120

Answers (1)

Omni
Omni

Reputation: 1022

I suspect that the "exponential growth" comes from the fact that in the event handler on_click, you create a connection between the timer and the event handler itself. So I would expect something like this to happen:

  • on_click is executed once and the timer is connected once to on_click
  • after a second, the timer runs out and triggers on_click. During execution of on_click, the timer is connected to on_click again.
  • after a second, the timer runs out and triggers on_click twice (due to 2 connections). Which in turn then generate 2 more connections.
  • etc.

What you should do is connect your timer to another function which actually does the thing you want to execute every second while the mouse button is down.

def on_release():
    self.timer.stop()

def on_press():
    self.timer.start(1000)

def every_second_while_pressed():
    print('click')

button.pressed.connect(on_press)
button.released.connect(on_release)
self.timer.timeout.connect(every_second_while_pressed)

Upvotes: 2

Related Questions