PyQt Tutorialübersicht
Hallo liebe Forumsmitglieder!
Ich bin neu in diesem Forum, da ich mich nun ernsthafter mit python auseinander setze. Ich habe bereits einen Onlinekurs und das Python-Buch von Galileo-Computing durchgearbeitet. Somit sind schon ein paar Grundkenntnisse vorhanden. Bevor ich mit Python begann habe ich viel in PHP gearbeitet und dort überwiegen Laravel angewendet.
Nun wieso dieser Post:
Ich habe mit Python und PyQT angefangen und soweit einfache "applets" geschrieben. Nun möchte ich ein größeres Projekt angehen, bei dem ich eine Anwendung schreiben möchte, die mehrere Unterfenster besitzt. Mit Konfigurationen arbeitet ein Layout hat und so weiter. Also im Grunde eine Anwendung, mit der es Spaß macht zu arbeiten.
Nun ich suche noch eine gute Tutorial-Übersicht zu:
- Layouten mit von Anwendungen mit PyQt, ich habe bisher mit den Styles gearbeitet im Creator, jedoch war das meist eher schlecht als recht.
- Multi-Window Anwendungen also wie gehe ich am schlausten mit mehreren Fenstern um, wie blockiere ich zum Beispiel ein Hintergrundfenster, oder wie schließe ich ein altes Fenster, wenn ich ein neues Aufrufe
- Laufzeitparalele Darstellung, wenn größere Datenmengen verarbeitet werden und mehrere Animationen/Berechnungen parallel laufen sollen
Ich danke für eure Hilfe und hoffe euch bald im Showroom die Anwendung zu präsentieren
Ich bin neu in diesem Forum, da ich mich nun ernsthafter mit python auseinander setze. Ich habe bereits einen Onlinekurs und das Python-Buch von Galileo-Computing durchgearbeitet. Somit sind schon ein paar Grundkenntnisse vorhanden. Bevor ich mit Python begann habe ich viel in PHP gearbeitet und dort überwiegen Laravel angewendet.
Nun wieso dieser Post:
Ich habe mit Python und PyQT angefangen und soweit einfache "applets" geschrieben. Nun möchte ich ein größeres Projekt angehen, bei dem ich eine Anwendung schreiben möchte, die mehrere Unterfenster besitzt. Mit Konfigurationen arbeitet ein Layout hat und so weiter. Also im Grunde eine Anwendung, mit der es Spaß macht zu arbeiten.
Nun ich suche noch eine gute Tutorial-Übersicht zu:
- Layouten mit von Anwendungen mit PyQt, ich habe bisher mit den Styles gearbeitet im Creator, jedoch war das meist eher schlecht als recht.
- Multi-Window Anwendungen also wie gehe ich am schlausten mit mehreren Fenstern um, wie blockiere ich zum Beispiel ein Hintergrundfenster, oder wie schließe ich ein altes Fenster, wenn ich ein neues Aufrufe
- Laufzeitparalele Darstellung, wenn größere Datenmengen verarbeitet werden und mehrere Animationen/Berechnungen parallel laufen sollen
Ich danke für eure Hilfe und hoffe euch bald im Showroom die Anwendung zu präsentieren
-
- User
- Beiträge: 379
- Registriert: Mittwoch 27. Juni 2018, 17:39
Layouts:Krie9er hat geschrieben: ↑Montag 30. März 2020, 20:21 - Layouten mit von Anwendungen mit PyQt, ich habe bisher mit den Styles gearbeitet im Creator, jedoch war das meist eher schlecht als recht.
- Multi-Window Anwendungen also wie gehe ich am schlausten mit mehreren Fenstern um, wie blockiere ich zum Beispiel ein Hintergrundfenster, oder wie schließe ich ein altes Fenster, wenn ich ein neues Aufrufe
- Laufzeitparalele Darstellung, wenn größere Datenmengen verarbeitet werden und mehrere Animationen/Berechnungen parallel laufen sollen
- QSplitter: Widgets werden nacheinander Vertikal/Horizontal (abhängig von QBoxLayout, also VBox oder HBox) platziert
- QHBoxLayout: *H*orizontal verlaufendes Layout
- QVBoxLayout: *V* verlaufendes Layout
- QGridLayout: Gitternetzlayout, als Bsp. Taschenrechnerinputs (1-7)
- für jedes Fenster erstellst du eine Klasse. Soll ein Fenster von einem anderen Fenster aufgerufen werden, lässt du das aktuelle Fenster verstecken ( ".hide()" ) und das andere anzeigen ( ".show()" )
warum auch immer, kommt es bei mir aber widerrum dazu, dass sich *manchmal* das Fenster leicht durch ".hide()" und dann mit ".show()" am Style verändert, weshalb ich auch schon einmal einfach die Transparenz dafür verwendet habe
- wenn du Threads meinst, dann gibt es '_thread' (für Funktionen bestimmt) und 'Thread' (für Klassen bestimmt)
Anhand der Begriffe lässt sich auch schnell was bei Google finden...
-
- User
- Beiträge: 379
- Registriert: Mittwoch 27. Juni 2018, 17:39
Warum ist es nicht für die Benutzung gedacht? Denn ich finde es eigentlich ziemlich hilfreich.
Das ist eine Design-Entscheidung der Python-Entwickler, die als die Art und Weise, wie man Threads benutzt threading.Threads vorgesehen haben, und nicht _threads. Die API von _threads ist sehr low-level und man muß viel implizites Wissen haben, um sie korrekt zu benutzen.
Wow vielen Dank für die schnell und freundliche Antwort!xXSkyWalkerXx1 hat geschrieben: ↑Dienstag 31. März 2020, 08:24Layouts:Krie9er hat geschrieben: ↑Montag 30. März 2020, 20:21 - Layouten mit von Anwendungen mit PyQt, ich habe bisher mit den Styles gearbeitet im Creator, jedoch war das meist eher schlecht als recht.
- Multi-Window Anwendungen also wie gehe ich am schlausten mit mehreren Fenstern um, wie blockiere ich zum Beispiel ein Hintergrundfenster, oder wie schließe ich ein altes Fenster, wenn ich ein neues Aufrufe
- Laufzeitparalele Darstellung, wenn größere Datenmengen verarbeitet werden und mehrere Animationen/Berechnungen parallel laufen sollen
- QSplitter: Widgets werden nacheinander Vertikal/Horizontal (abhängig von QBoxLayout, also VBox oder HBox) platziert
- QHBoxLayout: *H*orizontal verlaufendes Layout
- QVBoxLayout: *V* verlaufendes Layout
Multiwindow:
- QGridLayout: Gitternetzlayout, als Bsp. Taschenrechnerinputs (1-7)
Laufzeutparallele:
- für jedes Fenster erstellst du eine Klasse. Soll ein Fenster von einem anderen Fenster aufgerufen werden, lässt du das aktuelle Fenster verstecken ( ".hide()" ) und das andere anzeigen ( ".show()" )
warum auch immer, kommt es bei mir aber widerrum dazu, dass sich *manchmal* das Fenster leicht durch ".hide()" und dann mit ".show()" am Style verändert, weshalb ich auch schon einmal einfach die Transparenz dafür verwendet habe
- wenn du Threads meinst, dann gibt es '_thread' (für Funktionen bestimmt) und 'Thread' (für Klassen bestimmt)
Anhand der Begriffe lässt sich auch schnell was bei Google finden...
Ich habe mir den Thread direkt als Bookmark gespeichert!
Wie löst ihr die Organisation des Programms? Meine idee ist, die views in eigene Klassen zu schreiben, genauso wie die Prozesse. Also im Prinzip versuche ich MVC anzuwenden. Ist das Sinnvoll, leider geben meine Tutorialunterlagen hier keine Info zu best-practises oder cummon-standards, was das angeht.
Mit Layouten meinte ich eigentlich das optische Design des Programms. Ich hatte mich hier etwas zu ungenau ausgedrückt
@xXSkyWalkerXx1 ich habe noch eine tiefere Frage zu dem Laden der Fenster.
Ich habe folgenden Code in meiner StartApp stehen:
In meiner Klasse EffectOfVariationExample steht:
jetzt erhalte ich jedoch die folgende Fehlermeldung, wenn ich auf den Button zum Öffnen des neuen Fensters clicke:
Ehrlich gesagt verstehe ich nicht recht was dieses Fehlermeldung bedeuten soll. Wie realisierst du/ihr das öffnen (und schließen) von mehreren Fenstern in pyQt5?
Gruß
Ich habe folgenden Code in meiner StartApp stehen:
Code: Alles auswählen
import sys, os
from PyQt5 import QtWidgets, uic, QtGui
from myApp import EffectOnVariationExample
from PyQt5.QtGui import QIcon, QPixmap
class StartProgram(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = uic.loadUi(myApp/gui/navigatorwindow.ui', self)
self.show()
self.routing()
def routing(self):
self.ui.btnEffectOfVariationExample.clicked.connect(self.playEffectOfVariationExample)
def playEffectOfVariationExample(self):
widget =EffectOfVariationExample()
print("Test")
self.hide()
app = QtWidgets.QApplication(sys.argv)
lp = StartProgram()
sys.exit(app.exec_())
Code: Alles auswählen
from PyQt5 import QtWidgets, uic, QtGui
class EffectOnVariantionExample(QtWidgets.QWidget):
def __init__(self):
self.ui = uic.loadUi('gui/EffectOfVariationExample.ui', self)
self.show()
Code: Alles auswählen
widget = EffectOnVariationExample()
TypeError: 'module' object is not callable
Gruß
Zuletzt geändert von Krie9er am Dienstag 14. April 2020, 10:06, insgesamt 1-mal geändert.
Das hat mit Qt nichts zu tun. Hast du den Java-Style (und Python-Fehler) gemacht, deine Klasse in eine Datei gleichen Namens zu stecken? Das macht man nicht. Module sind in Python klein geschrieben, und sollten auch mehrere Klassen und Funktionen enthalten. Und dann importiert man *aus* diesen Modulen eine Klasse.
Dazu dann auch noch die Anmerkung, dass myApp nicht korrekt benamt ist, und mit my und App auch so ziemlich das nichtssagende, was man sich vorstellen kann. Da waere 'einhorn' oder so wirklich eine bessere Wahl.
Code: Alles auswählen
from myapp.effectonvariationmodule import EOnM
@►__deets__ Danke für die Anmerkungen, ja da schlägt meine PHP-Vergangenheit durch.
myApp war eigentlich nur ein Platzhalter xD
Ich habe den code jetzt auch verändert, sodass die Klasse geladen wird. Und das Widget auch angezeigt wird:
programm.py:
leanplayground/EffectOnVariation.py:
Aktuell suche ich noch eine Möglichkeit, wie ich beim schließen des neuen Fensters das NavigatorFenster wieder anzeige (mit .show())
myApp war eigentlich nur ein Platzhalter xD
Ich habe den code jetzt auch verändert, sodass die Klasse geladen wird. Und das Widget auch angezeigt wird:
programm.py:
Code: Alles auswählen
import sys, os
from PyQt5 import QtWidgets, uic, QtGui
from LeanPlayground import EffectOnVariationExample, Routing
from PyQt5.QtGui import QIcon, QPixmap
class StartProgram(QtWidgets.QMainWindow):
def __init__(self, parent=None):
self.rootDir = os.path.dirname(__file__)
print(os.path.join(self.rootDir, 'LeanPlayground/gui/navigatorwindow.ui'))
super().__init__(parent)
self.ui = uic.loadUi('LeanPlayground/gui/navigatorwindow.ui', self)
self.ui.licenseOwnerLogo.setPixmap(QPixmap('LeanPlayground/assets/apple-icon-120x120.png'))
self.show()
self.routing()
def routing(self):
self.ui.btnEffectOfVariationExample.clicked.connect(self.playEffectOfVariationExample)
def playEffectOfVariationExample(self):
widget = EffectOnVariationExample.playEOVE()
print("Test")
self.hide()
app = QtWidgets.QApplication(sys.argv)
app.setWindowIcon(QtGui.QIcon('LeanPlayground/assets/favicon_2.ico'))
lp = StartProgram()
sys.exit(app.exec_())
Code: Alles auswählen
from PyQt5 import QtWidgets, uic, QtGui
from PyQt5.QtGui import QIcon, QPixmap
class playEOVE(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = uic.loadUi('LeanPlayground/gui/EffectOfVariationExample.ui', self)
self.show()
Du solltest wirklich die Python Namenskonventionen adoptieren. EtwasMitGrossBuchstabenDarin ist in den Augen jedes erfahrenen Pythoneers eine Klasse. Damit verwirrst du uns und ggf. dich selbst.
Und wenn ein Fenster geschlossen wird, dann sollte es da doch ein Signal geben, an das man sich haengen kann.
Und wenn ein Fenster geschlossen wird, dann sollte es da doch ein Signal geben, an das man sich haengen kann.
Ich hatte eigentlich gedacht, dass ich mich an die Namenskonvention halte?
Welcher Part ist nicht korrekt?
Für Dateien und Klasse benutze ich PascalCases
für Funktionen und Variablen camelCases
Documentation
spricht jedoch von sneak cases für funktionen und variablen, jedoch hält sich selbst python nicht an diese Konvention oder? Deshalb dachte ich camelCases wären hier in Ordnung.
Besonders, da pyQt es auch so verwendet.
Ich habe das mit dem Hide and show nun so gelöst:
#program.py
#EffectOnVariationExample.py
Wie kann ich es eigentlich realisieren, dass ich nicht in jeder Klasse immer wieder die selben Sachen importieren muss? z.B. habe ich im Hauptprogramm ja schon PyQt5 importiert, wieso muss ich das in der Klasse erneut machen? Gibt es da eine Möglichkeit, dass die Imports vom Hauptprogramm vererbt werden?
Danke für die tolle Hilfe !
Welcher Part ist nicht korrekt?
Für Dateien und Klasse benutze ich PascalCases
für Funktionen und Variablen camelCases
Documentation
spricht jedoch von sneak cases für funktionen und variablen, jedoch hält sich selbst python nicht an diese Konvention oder? Deshalb dachte ich camelCases wären hier in Ordnung.
Besonders, da pyQt es auch so verwendet.
Ich habe das mit dem Hide and show nun so gelöst:
#program.py
Code: Alles auswählen
def playEffectOfVariationExample(self):
widget = EffectOnVariationExample.PlayEOVE(self)
print("Test")
self.hide()
Code: Alles auswählen
class PlayEOVE(QtWidgets.QWidget):
def __init__(self, mainWindow, parent=None):
super().__init__(parent)
self.ui = uic.loadUi('LeanPlayground/gui/EffectOfVariationExample.ui', self)
self.show()
self.mainWindow = mainWindow
def closeEvent(self, event):
self.mainWindow.show()
Danke für die tolle Hilfe !
Python haelt sich da durchaus dran. Aber Qt hat eben eine C++ bzw. eigene Namenskonvention, und um da keine Abweichung mit der nur in C++ verfuegbaren Dokumentation zu haben, folgt PyQt eben der. Fuer eigenen Code und Module mache ich das aber nicht.
Und nein. Jedes Modul muss seine importe selbst machen. Das du dich da aber auf Klassen beziehst, ist wie schon erwaehnt ein Missverstaendnis: in Python ist es durchaus ueblich, mehrere Klassen in einem Modul zu haben. Nicht ein Modul / Klasse. Womit dieses Problem auch etwas weniger schwer wiegt.
Und nein. Jedes Modul muss seine importe selbst machen. Das du dich da aber auf Klassen beziehst, ist wie schon erwaehnt ein Missverstaendnis: in Python ist es durchaus ueblich, mehrere Klassen in einem Modul zu haben. Nicht ein Modul / Klasse. Womit dieses Problem auch etwas weniger schwer wiegt.
Das ist wohl war ich persönlich finde es viel übersichtlicher pro klasse eine Datei zu haben. Aber das ist nur mein eigener Geschmack.__deets__ hat geschrieben: ↑Dienstag 14. April 2020, 11:34 ...
Und nein. Jedes Modul muss seine importe selbst machen. Das du dich da aber auf Klassen beziehst, ist wie schon erwaehnt ein Missverstaendnis: in Python ist es durchaus ueblich, mehrere Klassen in einem Modul zu haben. Nicht ein Modul / Klasse. Womit dieses Problem auch etwas weniger schwer wiegt.
Eine kleine Frage noch zum Laufzeitparalellen arbeiten in einem Fenster.
In der Anwendung soll eine Anwendung oben etwas Berechnen, wobei es für die Geschwindigkeit der Berechnung einen Slider gibt und einen Start und Stop Button.
Die "Bremse" habe ich über ein Time.sleep() implementiert. Nun möchte ich jedoch während der Berechnung die Geschwindigkeit umstellen oder die Berechnung Pausieren , bzw. auch gerne mit dem Fenster weiter interagieren.
Allerdings ist das so aktuell nicht möglich :-/
# dummyfunktion zum test ob es funktioniert
Sie wird gecalled durch
was wiederum durch
aufgerufen wird.
Im kern dreht sich nun meine Frage darum, wie ich weiter mit den Buttons interagieren kann, während eine Berechnung im Programm läuft.
Wahrscheinlich hab ich aktuell total Tomaten auf den Augen xD
In der Anwendung soll eine Anwendung oben etwas Berechnen, wobei es für die Geschwindigkeit der Berechnung einen Slider gibt und einen Start und Stop Button.
Die "Bremse" habe ich über ein Time.sleep() implementiert. Nun möchte ich jedoch während der Berechnung die Geschwindigkeit umstellen oder die Berechnung Pausieren , bzw. auch gerne mit dem Fenster weiter interagieren.
Allerdings ist das so aktuell nicht möglich :-/
# dummyfunktion zum test ob es funktioniert
Code: Alles auswählen
def simulate(self):
while self.simulation_active:
self.iteration = self.iteration + 1
self.machine_one_no_variation_status = random.randint(0,100)
self.write_to_frontend()
if self.iteration > 100:
self.simulation_active = False
if self.simulation_speed > 0:
time.sleep(self.simulation_speed/100)
Code: Alles auswählen
def play_simulation(self):
self.simulation_active = True
self.simulate()
Code: Alles auswählen
self.ui.btnPlaySimulation.clicked.connect(self.play_simulation)
Im kern dreht sich nun meine Frage darum, wie ich weiter mit den Buttons interagieren kann, während eine Berechnung im Programm läuft.
Wahrscheinlich hab ich aktuell total Tomaten auf den Augen xD
Es gibt zwei prinzipielle Moeglichkeiten:
- die Berechnung wird in lauter kleine Teilstuecke zerlegt, und du erledigst nur einige wenige davon, bevor die GUI wieder dran kommt. Fuer sowas benutzt man QTimer. Um das umzusetzen kann man in Python zB auf asyncio setzen.
- die Berechnung wird in einen extra Thread oder gar Prozess ausgelagert. Hier liegt die Herausforderung darin, dass man Threads und GUIs nicht einfach mischen kann, sonst kommt es zu Abstuerzen. Mit Qt gibt es Rezept, wie man Worker-Threads baut, die sicher mit signal/slot Verbindungen kommunizieren.
- die Berechnung wird in lauter kleine Teilstuecke zerlegt, und du erledigst nur einige wenige davon, bevor die GUI wieder dran kommt. Fuer sowas benutzt man QTimer. Um das umzusetzen kann man in Python zB auf asyncio setzen.
- die Berechnung wird in einen extra Thread oder gar Prozess ausgelagert. Hier liegt die Herausforderung darin, dass man Threads und GUIs nicht einfach mischen kann, sonst kommt es zu Abstuerzen. Mit Qt gibt es Rezept, wie man Worker-Threads baut, die sicher mit signal/slot Verbindungen kommunizieren.
Danke für den Hinweis, ich habe mir die offizielle Doku angesehen und das soweit, denke ich auch implementiert. Nun habe ich jedoch einen ganz merkwürdigen Bug.
Mein Fenster freezed immernoch jedoch glaube ich zu wissen wieso, nur weis ich nicht was der Grund ist wieso dies passiert.
Der Playbutton führt jetzt folgende Funktion aus:
Mein Thread ist noch einfach gehalten, da ich einfach nur testen möchte ob das Fenster dann nicht mehr freezed.
Nach meinem Verständnis sollte doch der thread nun einmal ausgeführt werden, oder?
Naja der Output in der Console zeigt, dass der Thread 2x ausgeführt wird o.O
Woran kann das liegen? Das merkwürdige ist, dass ich beim 2. Aufruf (der automatisch aus irgendeinem Grund passiert) dann die Thread Funktion habe.
Mein Fenster freezed immernoch jedoch glaube ich zu wissen wieso, nur weis ich nicht was der Grund ist wieso dies passiert.
Der Playbutton führt jetzt folgende Funktion aus:
Code: Alles auswählen
def play_simulation(self):
self.thread = ProductionProcess()
print('Aufruf')
self.thread.start()
Code: Alles auswählen
class ProductionProcess(QThread):
def __init__(self):
QThread.__init__(self)
self.iteration = 0
def __del__(self):
self.wait()
def run(self):
while self.iteration < 5:
print(self.iteration)
self.iteration = self.iteration + 1
self.sleep(2)
Naja der Output in der Console zeigt, dass der Thread 2x ausgeführt wird o.O
Code: Alles auswählen
Aufruf
0
1
2
3
4
Aufruf
0
1
2
3
4
Du hast nicht das implementiert, was ich im Kopf hatte, und meines Kenntnisstandes auch nicht die Empfehlung von Qt. Man ueberlaedt run nicht mehr selbst, und was man NIEMALS in Python macht ist, __del__ zu benutzen. Wo hast du das her?
Hier ist das Beispiel, das ich mal geschrieben habe. Es macht ein paar Dinge mehr, die kannst du rauswerfen.
viewtopic.php?f=24&t=44250&start=15#p335559
Zu deinem Problem kann man mit dem gezeigten Code nichts sagen, daraus ist das nicht erklaerbar.
Hier ist das Beispiel, das ich mal geschrieben habe. Es macht ein paar Dinge mehr, die kannst du rauswerfen.
viewtopic.php?f=24&t=44250&start=15#p335559
Zu deinem Problem kann man mit dem gezeigten Code nichts sagen, daraus ist das nicht erklaerbar.