Python-QT-ProgressBar
Wenn mit dem folgenden code meiner Anwendung Ständen nach ein paar Sekunden.
Und durch die Stände, ich meine hängt. Ich bekomme ein Fenster von Windows, die sagen warten oder force close.
Ich könnte hinzufügen, dass dies nur passiert, wenn ich klicken Sie entweder in der Statusleiste Fenster oder wenn ich auf der Außenseite, so verliert es den Fokus. Wenn ich nun den Beispiel und berühren Sie nicht alles, was es so funktioniert wie es sollte.
from PyQt4 import QtCore
from PyQt4 import QtGui
class ProgressBar(QtGui.QWidget):
def __init__(self, parent=None, total=20):
super(ProgressBar, self).__init__(parent)
self.name_line = QtGui.QLineEdit()
self.progressbar = QtGui.QProgressBar()
self.progressbar.setMinimum(1)
self.progressbar.setMaximum(total)
main_layout = QtGui.QGridLayout()
main_layout.addWidget(self.progressbar, 0, 0)
self.setLayout(main_layout)
self.setWindowTitle("Progress")
def update_progressbar(self, val):
self.progressbar.setValue(val)
Mit diesem etwa so:
app = QtGui.QApplication(sys.argv)
bar = ProgressBar(total=101)
bar.show()
for i in range(2,100):
bar.update_progressbar(i)
time.sleep(1)
Vielen Dank für jede Hilfe.
InformationsquelleAutor Tuim | 2012-11-07
Schreibe einen Kommentar Antworten abbrechen
Du musst angemeldet sein, um einen Kommentar abzugeben.
Müssen Sie erlauben die Ereignisse verarbeitet werden, während die Schleife ausgeführt wird, so dass die Anwendung kann reaktionsfähig bleiben.
Sogar noch wichtiger ist, für lang andauernde Aufgaben, die Sie benötigen, um eine Möglichkeit für den Benutzer, um die Schleife zu stoppen, sobald es gestartet wird.
Einen einfachen Weg, dies zu tun ist, starten Sie die Schleife mit einem timer, und dann in regelmäßigen Abständen rufen qApp.processEvents während die Schleife ausgeführt wird.
Hier ist ein demo-script, das das tut:
UPDATE
Davon aus, dass Sie mit der C-Implementierung von python (d.h. CPython), die Lösung dieses Problems hängt ganz auf die Art der Aufgabe(N), die zeitgleich mit der GUI. Mehr grundlegend, es ist bestimmt von CPython mit einem Global Interpreter Lock (GIL).
Ich werde nicht versuchen, eine Erklärung von CPython ist GIL: stattdessen werde ich einfach nur empfehlen, gerade diese ausgezeichnete PyCon video von Dave Beazley, und es dabei belassen.
In der Regel, wenn Sie versuchen, führen Sie eine GUI gleichzeitig mit einer hintergrund-task, die erste Frage ist: Ist die Aufgabe IO-bound oder CPU-gebunden?
Wenn es IO-bound (z.B. Zugriff auf das lokale Datei-system, das herunterladen aus dem internet, etc), dann ist die Lösung meist Recht einfach, weil CPython immer Veröffentlichungen der GIL für die I/O-Operationen. Der hintergrund-task kann einfach getan werden asynchron, oder ausgeführt durch eine Arbeitsthread und nichts besonderes getan werden muss, um zu halten die GUI reagiert.
Die wichtigsten Schwierigkeiten, die auftreten, mit CPU-gebundene Aufgaben, wenn es eine zweite Frage: Lässt sich die Aufgabe untergliedern sich in eine Reihe von kleinen Schritten?
Wenn es kann, dann die Lösung ist, periodisch Anfragen an den GUI-thread zu Prozess seinen aktuellen stack von anstehenden Veranstaltungen. Die demo-Skript oben ist ein grobes Beispiel für diese Technik. Mehr in der Regel, würde die Aufgabe durchgeführt werden in einem separaten worker-thread, der das emittieren würde ein gui-update-signal da in jedem Schritt der task abgeschlossen ist. (NB: es ist wichtig, um sicherzustellen, dass der worker-thread nie versucht, keine GUI-bezogenen Vorgänge selbst).
Aber wenn die Aufgabe nicht unten gebrochen werden, in kleinen Schritten, dann wird keiner der üblichen threading-Art-Lösungen arbeiten. Die GUI wird nur einfrieren, bis die Aufgabe abgeschlossen ist, ob threads verwendet oder nicht.
Für dieses Letzte Szenario, die einzige Lösung ist die Verwendung eines separaten Prozess, anstatt einen eigenen thread - also nutzen Sie die multiprocessing Modul. Natürlich, diese Lösung wird nur wirksam, wenn das Ziel-system hat mehrere CPU-Kerne zur Verfügung. Wenn es nur einen CPU-Kern zu spielen, gibt es im Grunde nichts, was getan werden kann, um zu helfen (andere als der Wechsel zu einer anderen Implementierung von Python oder einer anderen Sprache insgesamt).
Mein Skript ist nur eine einfache demo basiert auf dem code in deiner Frage. Es ist nicht eine Universelle Lösung, die funktioniert in allen Situationen. Sie müssen aktualisieren Sie Ihre Frage mit einer Erklärung, was Sie zu tun versuchen. Was sind diese "Aufgaben", die Sie erwähnen? Sind Sie CPU-bound oder IO-bound? Ist die Anwendung, führt die Aufgaben etwas, das Sie selber geschrieben haben, und können sich daher ändern? In welcher Sprache ist es geschrieben? Usw., usw.
Diese Aufgaben sind e-Installationen.g Auspacken von zip-Dateien, die Installation von msi - /deb-Pakete, die Dinge wie, dass. Aber das ist nicht sehr relevant für den Fall. Die Anwendung ist in Python geschrieben aswell und vollständig anpassbar. Auch ich erwarte nicht, ein copy-paste-fähig, Antwort! Ich erwarte einen Hinweis in die richtige Richtung und die, die Sie nicht scheinen, um die richtige Richtung für mich, die ich versucht habe. Keine straftat.
Im Gegenteil: die Art der Aufgaben ist wahrscheinlich der nur Sache, die relevant ist, um Ihren Fall. Bitte siehe das update meiner Antwort.
Vielen Dank für Ihre umfangreiche Antwort.
InformationsquelleAutor ekhumoro
wenn Sie tun, gui-Programmierung, die Sie benötigen, um irgendeine form von multi-threading, Sie hätte ein worker-thread und eine, die updates der gui und reagiert auf Maus-und Tastatur-Ereignisse. Es gibt eine Reihe von Möglichkeiten, dies zu tun. Ich empfehle, haben Sie einen Blick auf diese QProgressBar tutorial, das eine ausgezeichnete Arbeit Beispiel für die Verwendung QProgressBar.
In dem tutorial sind Sie mit QBasicTimer die Art und Weise, um Ertrag Steuern Sie zurück zum Haupt-thread, so dass es kann die Reaktion auf GUI-Ereignisse. Durch die Verwendung
time.sleep
in Ihrem code, den Sie die Blockierung für eine Sekunde der einzige thread, der ausgeführt wird.Ja, Sie sind, nicht verwenden
time.sleep()
.Ich aktualisiert, die Antwort weiter zu erklären, warum Sie Ihren code und die tutorials sind nicht die gleiche Sache zu tun.
Ich denke, die Erwähnung threading hier nur verwirrt die Dinge. Es gibt keine Gruppierung beteiligt, es geht nur um das zurückgeben der Steuerung an der Qt-event-loop, die app kann bleiben ansprechbar. Verschieben von Aufgaben in separate threads ist eine Strategie zur Erreichung dieser Ziele, aber es ist in keiner Weise erforderlich.
Vielleicht brauche ich etwas mehr Zusammenhang. Ich habe eine Konsole-Anwendung, die nicht eine Reihe von Aufgaben, die in einer seriellen Art und Weise. Ich möchte einfach zeigen, eine progressbar für dies und da QT ist die bevorzugte GUI-Bibliothek hier ich bin verpflichtet, es zu benutzen. Die Anwendung hat keine threading-Modell, außer für den Haupt-thread. So was brauche ich einfach ein GUI-frame (in einem neuen thread oder nicht) zeigen einen Fortschrittsbalken und aktualisieren diese bar immer, wenn eine Aufgabe abgeschlossen ist.
InformationsquelleAutor Marwan Alsabbagh