2017-10-18 6 views
0

Lorsque j'appuie sur un bouton, le code prend du temps. Pendant qu'il est en cours d'exécution, je veux éviter que le bouton ne réponde à un autre clic. Lorsque le code est terminé, le bouton peut être réactivé et d'autres clics doivent être traités.pyqt: comment désactiver plusieurs clics pour QPushButton?

Je suis en train de le faire en utilisant:

self.btn.blockSignals(True) 
    self.btn.setEnabled(False) 
    ... code ... 
    self.btn.blockSignals(True) 
    self.btn.setEnabled(False) 

Mais encore, si je clique sur ce bouton rapidement 10 fois, le code sera exécuté 10 fois ...

En réalité, je d déplace le code qui prend du temps vers un autre thread. (Edit: mais le problème est le même - je pense ?? En réalité, qui résout Voir accepted answer...)

Comment bloquer ou ignorer clique sur un bouton pendant que quelque chose est en marche?

est ici une version minimale de mon code:

import time 
import sys 
from PyQt4 import QtGui 

class Example(QtGui.QWidget): 

    def __init__(self): 
     super(Example, self).__init__() 
     self.initUI() 

    def initUI(self): 
     grid = QtGui.QGridLayout() 
     self.setLayout(grid) 
     self.btn = QtGui.QPushButton('Count') 
     grid.addWidget(self.btn, 1, 1) 
     self.txt1 = QtGui.QTextEdit() 
     grid.addWidget(self.txt1, 1, 2) 
     self.btn.clicked.connect(self.click) 
     self.count = 0 
     self.show() 

    def click(self): 
     # Here I want to block any further click in the button, but it is 
     # not working - clicking it 10 times quickly will run this 10 times... 
     self.btn.blockSignals(True) 
     self.btn.setEnabled(False) 
     time.sleep(2) # time consuming code... 
     self.count += 1 
     self.txt1.append(str(self.count)) 
     self.repaint() 
     self.btn.setEnabled(True) 
     self.btn.blockSignals(False) 


if __name__ == '__main__': 
    app = QtGui.QApplication(sys.argv) 
    ex = Example() 
    sys.exit(app.exec_()) 
+0

Je ne suis pas familier avec PyQt mais je trouve le lien suivant: [lien] (https://stackoverflow.com/questions/14087066/disabling -qpushbutton-before-a-task) Peut-être que vous devez ajouter 'QCoreApplication :: processEvents()' sous le 'self.btn.setEnabled (False)'. – Spezi94

+0

Sur mon système, 'processEvents' ne fonctionne pas, mais un thread le fait. – ekhumoro

+0

@ekhumoro vous voulez déplacer le code vers un nouveau fil? Devrait-on alors également bloquer blockSignals (False) sur le thread? – Raf

Répondre

1

Si vous mettez le code à long runnning dans un fil, le contrôle peut revenir à la boucle-événement principal une fois que le fil est démarré, ce qui permettra le GUI à mettre à jour immédiatement.

Voici une démonstration de base en fonction de votre exemple:

import sys 
from PyQt4 import QtGui, QtCore 

class Thread(QtCore.QThread): 
    def run(self): 
     QtCore.QThread.sleep(2) 

class Example(QtGui.QWidget): 
    def __init__(self): 
     super(Example, self).__init__() 
     self.initUI() 

    def initUI(self): 
     grid = QtGui.QGridLayout() 
     self.setLayout(grid) 
     self.btn = QtGui.QPushButton('Count') 
     grid.addWidget(self.btn, 1, 1) 
     self.txt1 = QtGui.QTextEdit() 
     grid.addWidget(self.txt1, 1, 2) 
     self.btn.clicked.connect(self.click) 
     self.thread = Thread() 
     self.thread.finished.connect(lambda: self.btn.setEnabled(True)) 
     self.show() 

    def click(self): 
     self.txt1.append('click') 
     if not self.thread.isRunning(): 
      self.btn.setEnabled(False) 
      self.thread.start() 

if __name__ == '__main__': 

    app = QtGui.QApplication(sys.argv) 
    ex = Example() 
    sys.exit(app.exec_()) 
+0

Brillant, merci! Il me manquait ce concept important: ne bloquez jamais la boucle d'événements principale avec des tâches chronophages. – Raf