2017-10-18 3 views
0

Wenn ich eine Taste drücke, läuft etwas zeitaufwendiger Code. Während der Ausführung möchte ich vermeiden, dass die Schaltfläche auf einen weiteren Klick reagiert. Wenn der Code fertig ist, kann die Schaltfläche wieder aktiviert werden und weitere Klicks sollten verarbeitet werden.pyqt: Wie kann man mehrere Klicks für QPushButton deaktivieren?

Ich versuche, das zu tun mit:

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

Aber noch, wenn ich diesen Knopf 10 mal schnell klicken, wird der Code 10-mal ausgeführt werden ...

In Wirklichkeit I‘ d verschiebe den zeitaufwendigen Code in einen anderen Thread. (Edit: aber immer noch das Problem ist das gleiche - ich glaube ?? In Wirklichkeit, die sie löst Siehe accepted answer...)

Wie blockiere ich oder ignorieren Klicks auf eine Schaltfläche, während etwas läuft?

Hier ist eine Minimalversion von meinem 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

ich mit PyQt nicht vertraut bin, aber ich fand folgenden Link: [link] (https://stackoverflow.com/questions/14087066/disabling -qpushbutton-before-a-task) Vielleicht müssen Sie 'QCoreApplication :: processEvents()' unterhalb der 'self.btn.setEnabled (False)' hinzufügen. – Spezi94

+0

Auf meinem System funktioniert 'processEvents' nicht, aber ein Thread tut es. – ekhumoro

+0

@ekhumoro Sie meinen den Code in einen neuen Thread verschieben? Sollte dann auch blockSignals (False) in den Thread verschoben werden? – Raf

Antwort

1

Wenn Sie den Lang runnning Code in einem Thread gestellt, Steuerung kann das Main Event-Schleife auf die zurück, sobald der Thread gestartet wird, die ermöglicht, Die GUI wird sofort aktualisiert.

ist hier eine grundlegende Demo basiert auf Ihrem Beispiel:

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

Brilliant, danke! Mir fehlte dieses wichtige Konzept: Blockiere niemals die Hauptereignisschleife mit zeitaufwendigen Aufgaben. – Raf

Verwandte Themen