PyQt4, QThread und eine Progressbar

Code-Stücke können hier veröffentlicht werden.
Antworten
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Nabend,

da ich vor dem Problem stand, in einer GUI eine länger dauernde Operation einzubauen, bei der ich gerne den Fortschritt anzeigen lassen wollte, habe ich mir mal eine kleine Demo-App gebastelt, die die grundlegenden Dinge bezüglich des Zusammenspiels von QThread-Subklassen und GUI-Elementen zeigt.

Bild

Vielleicht ist es ja auch für andere ein nettes Beispiel; speziell weil es ja einige Leutchens hier gibt, die die Doku zu PyQt wegen mangelnder Beispiele verteufeln ;-) (Wobei ich die Doku von Nokia zu diesem Thema sehr aufschlussreich fand)
Sobald lunar oder BlackJack das "abgesegnet" haben, kann man sich daran wohl orientieren :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@Hyperion: Ich bin glaube ich nicht in der Position Qt-Programme heilig zu sprechen, also besser lunar's Segen abwarten. :-)

Ich hätte nur eine Frage: Ist es üblich den `slot_*`-Präfix zu verwenden? Die sind ja an sich nichts besonderes -- soweit ich weiss geht jedes Python-"callable" als Empfänger von Signalen!?
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

BlackJack hat geschrieben: Ich hätte nur eine Frage: Ist es üblich den `slot_*`-Präfix zu verwenden? Die sind ja an sich nichts besonderes -- soweit ich weiss geht jedes Python-"callable" als Empfänger von Signalen!?
Da würde ich dir zustimmen. Das ist bei mir wohl noch ein Relikt aus der "pre"-new-style-slots-Ära :-D
Durch die Parameterflut der damaligen Syntax empfand ich es als einfacher zu lesen, wenn man das Präfix davor gesetzt hat. Ich denke jetzt kann man da auch getrost drauf verzichten.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
lunar

Im Großen und Ganzen schon ok. Die Präfixe finde ich wirklich unschön, aber das wurde ja bereits angesprochen. Wichtiger ist allerdings noch, das man eigentlich auf die Slot-Methoden vollkommen verzichten kann, und die Interaktion stattdessen über zusätzliche Signal-Slot-Verbindungen zusammen mit partiellen Funktionen noch weiter entkoppeln und noch mehr Quelltext sparen könnte. Daneben gibt es einige Kleinigkeiten: Der Import von "Qt" ist überflüssig, ebenso wie der überschriebene Konstruktor in der Thread-Klasse, der ja eigentlich gar nichts tut.

Zudem ist es bei solchen Threads oft so, dass Minimum und insbesondere Maximum der Schritte dynamisch nach dem Start des Threads berechnet werden. Daher ist es sinnvoll, die Ergebnisse dieser Berechnung mit zwei zusätzlichen Signalen nach außen zu geben, um das Intervall des Fortschrittsbalkens entsprechend anzupassen.

Insofern: Segen erteilt ;)

Wenn es Dir recht ist, würde ich dieses Beispiel gerne etwas überarbeiten und meiner Snippet-Sammlung hinzufügen.

Edit: Ach ja, in einer großen Applikation mit vielen Hintergrundaufgaben würde man übrigens eher QRunnable in Verbindung mit QThreadPool verbinden. Zudem ist diese Aufgabenstellung eine, in der C++ Python tatsächlich etwas voraus hat. Qt bietet mit QtConcurrent eine sehr komfortable Möglichkeit, Datensätze parallel zu verarbeiten, inklusive des ganzen Drumherums wie Abbruch der Verarbeitung oder Fortschrittsmeldungen. Allerdings setzt diese Bibliothek stark auf Templates auf, ist daher nicht so ohne weiteres anzubinden und steht in PyQt4 nicht zur Verfügung. Bei Interesse habe ich für die Anwendung von QtConcurrent in C++ auch ein Beispiel parat, aber im Prinzip ist das hier ja off-topic.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

lunar hat geschrieben: Insofern: Segen erteilt ;)

Wenn es Dir recht ist, würde ich dieses Beispiel gerne etwas überarbeiten und meiner Snippet-Sammlung hinzufügen.
Das wäre mir sogar sehr recht! :-) Bin gespannt auf Dein Änderungen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
lunar

https://bitbucket.org/lunar/snippets/sr ... rogress.py

Änderungen
  • Die trivialen Slot-Methoden sind entfallen.
  • Der Thread kann nun von außen beendet werden.
  • Die GUI ist ohne Designer implementiert, damit das Snippet keine Abhängigkeiten hat.
  • Menü und Knopf (imho hässlich) sind durch eine Werkzeugleiste mit Aktionen (inklusive hübscher Icons ;) ) ersetzt.
  • Ein paar erklärende Kommentare sind hinzugekommen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Sieht auf den ersten Blick sehr rund aus. Und ist einiges drin, was ich noch nicht kannte ;-)

Werde ich mir mal in einer ruhigen Minute genauer ansehen.

Danke auf jeden Fall für die Verbesserungen!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Da das Thema ab und an noch hochkocht und die Links hier nicht mehr erreichbar sind, hier der Link zum Repo, das die "finale" Version beinhaltet, die lunar programmiert hatte:
https://github.com/lunaryorn/snippets/b ... rogress.py
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
lunar

Oh, ich wusste nicht, dass überhaupt noch irgendjemand dieses Repo verwendet. Wenn Du tatsächlich noch Interesse an diesen Sachen hast, dann wäre es mir lieber, wenn Du das Repo forken würdest, denn wie gesagt “OLD, OUTDATED and UNMAINTAINED”, und ich neige dazu, Github-Repos, die ich nicht brauche, irgendwann auch mal zu löschen.

PS: Oha, 20 Seiten ungelesene Beiträge. Lustig, was so passiert, wenn man sich ein Jahr lang nicht anmeldet :)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

lunar hat geschrieben:Oh, ich wusste nicht, dass überhaupt noch irgendjemand dieses Repo verwendet. Wenn Du tatsächlich noch Interesse an diesen Sachen hast, dann wäre es mir lieber, wenn Du das Repo forken würdest, denn wie gesagt “OLD, OUTDATED and UNMAINTAINED”, und ich neige dazu, Github-Repos, die ich nicht brauche, irgendwann auch mal zu löschen.
Gute Idee! Verwenden tue ich es eigentlich auch nicht mehr... aber es kommen halt doch noch Fragen dazu, die man damit gut beantworten kann :-)
lunar hat geschrieben: PS: Oha, 20 Seiten ungelesene Beiträge. Lustig, was so passiert, wenn man sich ein Jahr lang nicht anmeldet :)
Na dann viel Spaß beim Lesen :mrgreen:
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
lunar

Hyperion hat geschrieben:
lunar hat geschrieben: PS: Oha, 20 Seiten ungelesene Beiträge. Lustig, was so passiert, wenn man sich ein Jahr lang nicht anmeldet :)
Na dann viel Spaß beim Lesen :mrgreen:
Oh, ich glaube, das lasse ich lieber ;)
Antworten