QPushButton reacts to press when disabled.
-
Hi,
Problem
I have a simple gui with a push button. When the button is pressed a function is called. I have noticed that the button can be pressed multiple times and that the callback function is ran multiple times. As if the callbacks are queued up.To sort this I have tried to use setEnable(False), which do disable the button (it is greyed out). However, the button still register presses, and when the callback function is completed, it starts again. Pressing the button enough times causes the application to crash.
What i want
I want to do something like this.self.btn = QPushButton('Refresh', self) self.btn.clicked.connect(self.refresh) def refresh(self): self.btn.setEnabled(False) # do something that takes a couple of seconds self.btn.setEnabled(True)I have tried
- Using a QTimer to handle the setEnable() method, and then call the function if the button is pressed and disabled.
- Using a QThread to basically do the same as above.
- Using a dummy-button. Identical to the original button, but without any callback-functions.
- Showing/hiding the button.
-
This simple test works with pyside6
import sys from PySide6.QtWidgets import QApplication, QWidget, QPushButton from PySide6.QtCore import QTimer class Widget(QWidget): def __init__(self): QWidget.__init__(self) self.btn = QPushButton('Refresh', self) self.btn.clicked.connect(self.refresh) self.btnTimer = QTimer(self) self.btnTimer.setInterval(2000) self.btnTimer.setSingleShot(True) self.btnTimer.timeout.connect(self.timerTimeout) def refresh(self): self.btn.setEnabled(False) self.btnTimer.start() print('Button was pressed, starting timer') def timerTimeout(self): self.btn.setEnabled(True) print('In Timer TimeOut') if __name__ == "__main__": app = QApplication([]) window = Widget() window.show() sys.exit(app.exec()) -
Hi,
Problem
I have a simple gui with a push button. When the button is pressed a function is called. I have noticed that the button can be pressed multiple times and that the callback function is ran multiple times. As if the callbacks are queued up.To sort this I have tried to use setEnable(False), which do disable the button (it is greyed out). However, the button still register presses, and when the callback function is completed, it starts again. Pressing the button enough times causes the application to crash.
What i want
I want to do something like this.self.btn = QPushButton('Refresh', self) self.btn.clicked.connect(self.refresh) def refresh(self): self.btn.setEnabled(False) # do something that takes a couple of seconds self.btn.setEnabled(True)I have tried
- Using a QTimer to handle the setEnable() method, and then call the function if the button is pressed and disabled.
- Using a QThread to basically do the same as above.
- Using a dummy-button. Identical to the original button, but without any callback-functions.
- Showing/hiding the button.
@martinmaeland
Hello and welcome.You should not be having so much trouble. For example, the code you showed should work (AFAIK), it should not generate new
clickedsignal while disabled. Do you do anything which could affect this in your# do something that takes a couple of seconds? -
Hello @JonB,
Thank you for the response.
I have the same issue if i do it like this:
def refresh(self): self.btn.setEnabled(False) sleep(2) self.btn.setEnabled(True) -
Hello @JonB,
Thank you for the response.
I have the same issue if i do it like this:
def refresh(self): self.btn.setEnabled(False) sleep(2) self.btn.setEnabled(True)@martinmaeland
When you use this code, do you visually see the button disabled before the 2 second sleep? -
This simple test works with pyside6
import sys from PySide6.QtWidgets import QApplication, QWidget, QPushButton from PySide6.QtCore import QTimer class Widget(QWidget): def __init__(self): QWidget.__init__(self) self.btn = QPushButton('Refresh', self) self.btn.clicked.connect(self.refresh) self.btnTimer = QTimer(self) self.btnTimer.setInterval(2000) self.btnTimer.setSingleShot(True) self.btnTimer.timeout.connect(self.timerTimeout) def refresh(self): self.btn.setEnabled(False) self.btnTimer.start() print('Button was pressed, starting timer') def timerTimeout(self): self.btn.setEnabled(True) print('In Timer TimeOut') if __name__ == "__main__": app = QApplication([]) window = Widget() window.show() sys.exit(app.exec()) -
@martinmaeland
When you use this code, do you visually see the button disabled before the 2 second sleep?Yes, the button does visually disable for 2 seconds.
-
This simple test works with pyside6
import sys from PySide6.QtWidgets import QApplication, QWidget, QPushButton from PySide6.QtCore import QTimer class Widget(QWidget): def __init__(self): QWidget.__init__(self) self.btn = QPushButton('Refresh', self) self.btn.clicked.connect(self.refresh) self.btnTimer = QTimer(self) self.btnTimer.setInterval(2000) self.btnTimer.setSingleShot(True) self.btnTimer.timeout.connect(self.timerTimeout) def refresh(self): self.btn.setEnabled(False) self.btnTimer.start() print('Button was pressed, starting timer') def timerTimeout(self): self.btn.setEnabled(True) print('In Timer TimeOut') if __name__ == "__main__": app = QApplication([]) window = Widget() window.show() sys.exit(app.exec())I actually tried this myself after I posted this, and it worked! As long as the timer interval is long enough. Found that 100 ms is enough for it to be pretty responsive and not queue up the callbacks.
Thank you :)