Wie kann ich Widgets ansprechen(pyside6)? (2025)

This topic has been deleted. Only users with topic management privileges can see it.

  • MOffline

    MOffline

    Master_Shredder

    wrote on last edited by

    #1

    Hallo,

    ich habe ein Problem. Ich habe die .ui Datei direkt eingefügt, und jetzt kann ich meine Widgets nicht anspechen.

    Im ganzen möchte ich durch ein click() Signal, den inhalt einer SpinBox abrufen und in eine Methode geben.
    Diese soll dann mit ermittelten Ergebnissen Labels setten.

    Hier der Quellcode:

    import sysfrom PySide6.QtUiTools import QUiLoaderfrom PySide6.QtWidgets import QApplicationfrom PySide6.QtCore import QFile, QIODevicefrom Abrechnung import Abrechnungclass Verbrauchsrechner: """Main Klasse hier startet das Programm"""def berechne(self): eingegebener_zaehlerstand = self.ui.spin_box_eingabe.value() abrechnung = Abrechnung.eingabe_zaehlerstand(eingegebener_zaehlerstand) self.ui.arbeitspreis_netto.setText(f"{abrechnung.arbeitspreis_netto:.2f} €") self.ui.arbeitspreis_brutto.setText(f"{abrechnung.arbeitspreis_brutto:.2f} €") self.ui.grundpreis_netto.setText(f"{abrechnung.grundpreis_tagesgenau_netto:.2f} €") self.ui.grundpreis_brutto.setText(f"{abrechnung.grundpreis_tagesgenau_brutto:.2f} €") self.ui.gesamtpreis_netto.setText(f"{abrechnung.gesamtbetrag_netto:.2f} €") self.ui.gesamtpreis_brutto.setText(f"{abrechnung.gesamtbetrag_brutto:.2f} €") self.ui.abschlag_bis_jetzt.setText(f"{abrechnung.bisheriger_gezahlter_abschlag:.2f} €") self.ui.abschlag_ende_des_jahres.setText(f"{abrechnung.abschlag_ende_des_jahres:.2f} €") self.ui.gp_abz_abschlag_bj.setText(f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag:.2f} €") self.ui.gp_abz_abschlag_ej.setText(f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag_ende_des_jahres:.2f}")def main(): app = QApplication(sys.argv) ui_file_name = "GUI/verbrauchsrechner_gui.ui" ui_file = QFile(ui_file_name) if not ui_file.open(QIODevice.ReadOnly): print(f"Cannot open {ui_file_name}: {ui_file.errorString()}") sys.exit(-1) loader = QUiLoader() window = loader.load(ui_file) ui_file.close() if not window: print(loader.errorString()) sys.exit(-1) window.show() sys.exit(app.exec())if __name__ == '__main__': main()

    MFG Master_Shredder

    P1 ReplyLast reply

  • PPl45m4

    @Master_Shredder said in Wie kann ich Widgets ansprechen(pyside6)?:

    🤦Ich musste gerade feststellen, dass das Programm in der Konstellation mit findChild() beim Button läuft!

    Haha ok, gut zu hören.

    Vielleicht kam es bei dir zu Verwirrung 😅.

    Ja weil ich mir nicht mehr sicher war wie es in Python funktioniert mit der Verbindung. Ob die Klasse, wo eine Funktion mit einem Signal verbunden ist, ein QObject sein muss oder nicht (in C++ kann man nur QObject Klassen direkt verbinden).
    Anscheinend muss es in PySide nicht so sein...

    Funktioniert, sichtlich, wunderbar.

    Ja das ist einer der "empfohlenen Wege", wie man den QtDesigner nutzt. Ob man es so macht, ist ja jedem selbst überlassen.

    @Master_Shredder said in Wie kann ich Widgets ansprechen(pyside6)?:

    "Ich nehme die *.uic-Dateien, weil Quelltext generieren ein unnötiger Zwischenschritt ist, und sich dann auch das Problem nicht stellt generierte Dateien in der Versionsverwaltung zu haben oder nicht.

    Gegen die Warnungen kannst Du nicht wirklich was machen, ausser sie komplett abschalten. Damit muss man bei dynamischen Programmiersprachen halt leben das es Grenzen bei der statischen Analyse von Quelltext gibt."

    Die Verwendung vom Designer macht den Code bzw. Anwendung etwas schwerer zu debuggen und für Dritte zu verstehen.
    Deswegen wird in professionellen QtWidget-Apps meist kein Designer genutzt (QML/QtDesign Studio ist nochmal eine andere Geschichte). Gerade weil man irgendwann sehr limitiert ist, in dem was man tun/umsetzen kann. Daher ist man dann zwangsläufig auf eine (unübersichtliche) Hybrid-Lösung angewiesen.
    Aus dem Grund verzichten viele eher komplett auf den QtDesigner und die .ui Dateien und schreiben ihre GUI selbst. Resultiert dann zwar in mehr Code, ist aber übersichtlicher. Da sieht dann jeder Leser von dem Code direkt was er bekommt (zu erwarten hat) und muss nicht noch irgendwelche XML Blöcke oder automatisch generierte Dateien durchsuchen.

    Auch wenn du sagst, dass es dir aufwändig vorkommt, alles im Code per Hand zu schreiben, müsstest du ja bei dem QUiLoader auch Abstriche machen. Um dort auf die internen Widgets zuzugreifen, ist es dann nötig sie z.B. mit findChild im QObject-Baum vom (durch den Loader erzeugten) Widget zu suchen.
    Dazu dann das uic Tool (User Interface Compiler), auf das man auch verzichten kann, wenn keine .ui im Spiel ist (Stichwort Codegenerierung).

    Betrifft das gesamte Qt Framework, egal in welcher Form und Sprache man es einsetzt.
    In C++ durch den UICompiler von Qt:

    • wird meinWidget.ui zu ui_meinWidget.h

    Diesen Header kann man dann einbinden. Daraus eine Instanz der UI-Klasse erstellen und ist dann in der Lage die Widgets aus der UI - Datei mit ui->objektname zu adressieren.

    In Python entsprechend:

    • meinWidget.ui zu meinWidget.py

    Alles in "Qt für Python", egal ob PySide oder PyQt wurde von C++ adaptiert, da Qt ein C++ GUI Framework ist. PySide und PyQt sind Bindings, die später dazuentwickelt wurden.
    Darum musste auch ein Tool zum Übersetzen der UI Dateien in etwas "Python-Nutzbares" existieren, auch wenn diese zusätzliche Codegenerierung nicht der Philosophie einer "dynamischen" und Interpreter-Sprache (wie Python) entspricht.

    Da deine UI jetzt nicht besonders komplex ist, wäre es sogar einfacher sie ohne jedliche UI oder den Designer zusammenzusetzen. So würde ich es machen, nach einigen Jahren Erfahrung mit Qt (mag am Anfang aber etwas schwieriger sein)
    Der Designer ist verlockend weil es relativ schnell und einfach ist, aber dann muss man auch mit den Kehrseiten leben :)
    Entweder die Code-Generierung durch UIC oder, beim QUiLoader etwas umständlich auf die Widgets zuzugreifen zu müssen.
    Sonst bleibt nur der Weg "zu Fuß" ;-)

    Im Endeffekt ist alles Geschmackssache bzw. auch etwas abhängig vom Use-Case und Art der App, die man entwickelt (und für wen).

    Zu den Warnungen kann ich leider nichts sagen... Möglicherweise kann man die Qt Syntax der IDE beibringen.
    Hab dazu den Bugreport hier gefunden:

    Schon mal VS Code statt PyCharm versucht?

    Ich würde es dann nach der von dir erwähnten Methode Nr. 1 machen. Da es für mich, aus der Sicht von Python, keinen Sinnvollen Grund gibt es anders zu machen. Und außerdem kenne ich mich auch nicht so gut aus, dass ich selbst entscheiden könnte ob die Warnungen zu ignorieren sind.

    Ja, dies habe ich in dem Post obendrüber ja schon umgesetzt. Kann ich dies so lassen, oder gibt es verbesserung's Vorschläge?

    Denke zum Lernen und Herumexperimentieren mit Qt und QtDesigner ist das die beste und einfachste Lösung.
    So muss man sich keine Gedanken machen, und hat innerhalb der Klasse überall vollen Zugriff auf die UI mittels self.ui.<objekt_name>.
    Alles Weitere kommt dann mit der Zeit :)

    MOffline

    MOffline

    Master_Shredder

    wrote on last edited by

    #12

    @Pl45m4 said in Wie kann ich Widgets ansprechen(pyside6)?:

    Ja das ist einer der "empfohlenen Wege", wie man den QtDesigner nutzt. Ob man es so macht, ist ja jedem selbst überlassen.

    Ja so lasse ich es auch jetzt. Das sieht gut aus. Bevor ich mich auf Irrwege mache und am Ende nichts davon verstehe.

    Denke zum Lernen und Herumexperimentieren mit Qt und QtDesigner ist das die beste und einfachste Lösung.
    So muss man sich keine Gedanken machen, und hat innerhalb der Klasse überall vollen Zugriff auf die UI mittels self.ui.<objekt_name>.
    Alles Weitere kommt dann mit der Zeit :)

    Ja denke ich auch. Dies ist wunderbar :).

    OK. Dann dankeschön für die Hilfe.

    1 ReplyLast reply

  • MMaster_Shredder

    Hallo,

    ich habe ein Problem. Ich habe die .ui Datei direkt eingefügt, und jetzt kann ich meine Widgets nicht anspechen.

    Im ganzen möchte ich durch ein click() Signal, den inhalt einer SpinBox abrufen und in eine Methode geben.
    Diese soll dann mit ermittelten Ergebnissen Labels setten.

    Hier der Quellcode:

    import sysfrom PySide6.QtUiTools import QUiLoaderfrom PySide6.QtWidgets import QApplicationfrom PySide6.QtCore import QFile, QIODevicefrom Abrechnung import Abrechnungclass Verbrauchsrechner: """Main Klasse hier startet das Programm"""def berechne(self): eingegebener_zaehlerstand = self.ui.spin_box_eingabe.value() abrechnung = Abrechnung.eingabe_zaehlerstand(eingegebener_zaehlerstand) self.ui.arbeitspreis_netto.setText(f"{abrechnung.arbeitspreis_netto:.2f} €") self.ui.arbeitspreis_brutto.setText(f"{abrechnung.arbeitspreis_brutto:.2f} €") self.ui.grundpreis_netto.setText(f"{abrechnung.grundpreis_tagesgenau_netto:.2f} €") self.ui.grundpreis_brutto.setText(f"{abrechnung.grundpreis_tagesgenau_brutto:.2f} €") self.ui.gesamtpreis_netto.setText(f"{abrechnung.gesamtbetrag_netto:.2f} €") self.ui.gesamtpreis_brutto.setText(f"{abrechnung.gesamtbetrag_brutto:.2f} €") self.ui.abschlag_bis_jetzt.setText(f"{abrechnung.bisheriger_gezahlter_abschlag:.2f} €") self.ui.abschlag_ende_des_jahres.setText(f"{abrechnung.abschlag_ende_des_jahres:.2f} €") self.ui.gp_abz_abschlag_bj.setText(f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag:.2f} €") self.ui.gp_abz_abschlag_ej.setText(f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag_ende_des_jahres:.2f}")def main(): app = QApplication(sys.argv) ui_file_name = "GUI/verbrauchsrechner_gui.ui" ui_file = QFile(ui_file_name) if not ui_file.open(QIODevice.ReadOnly): print(f"Cannot open {ui_file_name}: {ui_file.errorString()}") sys.exit(-1) loader = QUiLoader() window = loader.load(ui_file) ui_file.close() if not window: print(loader.errorString()) sys.exit(-1) window.show() sys.exit(app.exec())if __name__ == '__main__': main()

    MFG Master_Shredder

    POnline

    POnline

    Pl45m4

    wrote on last edited by Pl45m4

    #2

    Hi @Master_Shredder, willkommen im Forum,

    vorab, ich bin nicht der große PySide/PyQt-Nutzer, bevorzuge eher C++, aber hier trotzdem ein paar Dinge, die mir aufgefallen sind:

    Im ganzen möchte ich durch ein click() Signal, den inhalt einer SpinBox abrufen und in eine Methode geben.
    Diese soll dann mit ermittelten Ergebnissen Labels setten.

    Ein Click worauf? Ein clicked() Signal muss ja irgendwoher kommen. Was genau soll geklickt werden? Sehe bei dir nämlich keinen Button.

    Ich habe die .ui Datei direkt eingefügt, und jetzt kann ich meine Widgets nicht anspechen.

    Ja weil es kein self.ui mehr gibt.
    Wenn ich mich nicht irre, wird self.ui auch in Qt für Python durch setupUi initialisiert (ebenso in C++, nur halt als ::UI Member im Header statt "self").

    window = loader.load(ui_file)

    Der QUiLoader gibt ein QWidget zurück, welches aus der geladenen *.ui Datei erstellt wurde.
    Damit kannst du dann weiter arbeiten, die Sub-Widgets herausladen und dann die Signale verbinden.

    z.B. so:

    button = self.window.findChild(QtWidgets.QPushButton, "button_object_name")button.clicked.connect(self.berechne)

    Ich würde übrigens das Laden der UI File in den Konstruktor deiner Verbrauchsrechner-Klasse schieben und nicht unbedingt in der Main machen. So kannst du dann auch direkt das geladene Widget window als Klassenvariable nutzen und hast dann mit self.window Zugriff darauf (siehe oben wie in meinem Code)...

    Keine Garantie dass das funktioniert... aber so würde man einen Button click mit deiner Berechne Funktion verbinden.
    (Vielleicht findet sich hier noch ein PySide Experte, der mich möglicherweise korrigiert oder dir noch mehr Tipps geben kann)

    Aber was spricht denn dagegen, die *.ui Datei selbst zu einer *.py Klasse zu kompilieren und dann so zu nutzen wie bisher?
    Noch besser wäre natürlich die Widgets selbst zu coden, dann spart man sich den Designer und die ganzen ui Files komplett :)
    Aber am Anfang muss man sich erstmal damit anfreunden :)

    If debugging is the process of removing software bugs, then programming must be the process of putting them in.

    ~E. W. Dijkstra

    M1 ReplyLast reply

  • PPl45m4

    Hi @Master_Shredder, willkommen im Forum,

    vorab, ich bin nicht der große PySide/PyQt-Nutzer, bevorzuge eher C++, aber hier trotzdem ein paar Dinge, die mir aufgefallen sind:

    Im ganzen möchte ich durch ein click() Signal, den inhalt einer SpinBox abrufen und in eine Methode geben.
    Diese soll dann mit ermittelten Ergebnissen Labels setten.

    Ein Click worauf? Ein clicked() Signal muss ja irgendwoher kommen. Was genau soll geklickt werden? Sehe bei dir nämlich keinen Button.

    Ich habe die .ui Datei direkt eingefügt, und jetzt kann ich meine Widgets nicht anspechen.

    Ja weil es kein self.ui mehr gibt.
    Wenn ich mich nicht irre, wird self.ui auch in Qt für Python durch setupUi initialisiert (ebenso in C++, nur halt als ::UI Member im Header statt "self").

    window = loader.load(ui_file)

    Der QUiLoader gibt ein QWidget zurück, welches aus der geladenen *.ui Datei erstellt wurde.
    Damit kannst du dann weiter arbeiten, die Sub-Widgets herausladen und dann die Signale verbinden.

    z.B. so:

    button = self.window.findChild(QtWidgets.QPushButton, "button_object_name")button.clicked.connect(self.berechne)

    Ich würde übrigens das Laden der UI File in den Konstruktor deiner Verbrauchsrechner-Klasse schieben und nicht unbedingt in der Main machen. So kannst du dann auch direkt das geladene Widget window als Klassenvariable nutzen und hast dann mit self.window Zugriff darauf (siehe oben wie in meinem Code)...

    Keine Garantie dass das funktioniert... aber so würde man einen Button click mit deiner Berechne Funktion verbinden.
    (Vielleicht findet sich hier noch ein PySide Experte, der mich möglicherweise korrigiert oder dir noch mehr Tipps geben kann)

    Aber was spricht denn dagegen, die *.ui Datei selbst zu einer *.py Klasse zu kompilieren und dann so zu nutzen wie bisher?
    Noch besser wäre natürlich die Widgets selbst zu coden, dann spart man sich den Designer und die ganzen ui Files komplett :)
    Aber am Anfang muss man sich erstmal damit anfreunden :)

    MOffline

    @Pl45m4 said in Wie kann ich Widgets ansprechen(pyside6)?:

    Hi @Master_Shredder, willkommen im Forum,

    Hi, Dankeschön

    @Pl45m4 said in Wie kann ich Widgets ansprechen(pyside6)?:

    Ein Click worauf? Ein clicked() Signal muss ja irgendwoher kommen. Was genau soll geklickt werden? Sehe bei dir nämlich keinen Button.

    Ja ein Button.

    @Pl45m4 said in Wie kann ich Widgets ansprechen(pyside6)?:

    Der QUiLoader gibt ein QWidget zurück, welches aus der geladenen *.ui Datei erstellt wurde.
    Damit kannst du dann weiter arbeiten, die Sub-Widgets herausladen und dann die Signale verbinden.

    Ah ja so etwas habe ich mir schon gedacht, hatte auch schon mal ein Beispiel gesehen.

    @Pl45m4 said in Wie kann ich Widgets ansprechen(pyside6)?:

    Ich würde übrigens das Laden der UI File in den Konstruktor deiner Verbrauchsrechner-Klasse schieben und nicht unbedingt in der Main machen. So kannst du dann auch direkt das geladene Widget window als Klassenvariable nutzen und hast dann mit self.window Zugriff darauf (siehe oben wie in meinem Code)...

    Ja dies halte ich auch für eine gute Idee, habe es auch so umgesetzt.

    Jetzt habe ich nur das Problem, dass ich diese Fehlermeldungen hier bekomme:

    Unresolved attribute reference 'clicked' for class 'object'
    Unresolved attribute reference 'berechne' for class 'Verbrauchsrechner'

    import sysfrom PySide6 import QtWidgetsfrom PySide6.QtUiTools import QUiLoaderfrom PySide6.QtWidgets import QApplicationfrom PySide6.QtCore import QFile, QIODevicefrom Abrechnung import Abrechnungclass Verbrauchsrechner: """Main Klasse hier startet das Programm""" def __init__(self): ui_file_name = "GUI/verbrauchsrechner_gui.ui" ui_file = QFile(ui_file_name) if not ui_file.open(QIODevice.ReadOnly): print(f"Cannot open {ui_file_name}: {ui_file.errorString()}") sys.exit(-1) loader = QUiLoader() window = loader.load(ui_file) ui_file.close() if not window: print(loader.errorString()) sys.exit(-1) window.show() # Slot eingerichtet button = window.findChild(QtWidgets.QPushButton, "button_OK") button.clicked.connect(self.berechne)def berechne(self): eingegebener_zaehlerstand = self.window.spin_box_eingabe.value() abrechnung = Abrechnung.eingabe_zaehlerstand(eingegebener_zaehlerstand) self.window.arbeitspreis_netto.setText(f"{abrechnung.arbeitspreis_netto:.2f} €") self.window.arbeitspreis_brutto.setText(f"{abrechnung.arbeitspreis_brutto:.2f} €") self.window.grundpreis_netto.setText(f"{abrechnung.grundpreis_tagesgenau_netto:.2f} €") self.window.grundpreis_brutto.setText(f"{abrechnung.grundpreis_tagesgenau_brutto:.2f} €") self.window.gesamtpreis_netto.setText(f"{abrechnung.gesamtbetrag_netto:.2f} €") self.window.gesamtpreis_brutto.setText(f"{abrechnung.gesamtbetrag_brutto:.2f} €") self.window.abschlag_bis_jetzt.setText(f"{abrechnung.bisheriger_gezahlter_abschlag:.2f} €") self.window.abschlag_ende_des_jahres.setText(f"{abrechnung.abschlag_ende_des_jahres:.2f} €") self.window.gp_abz_abschlag_bj.setText(f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag:.2f} €") self.window.gp_abz_abschlag_ej.setText(f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag_ende_des_jahres:.2f}")def main(): app = QApplication(sys.argv) sys.exit(app.exec())if __name__ == '__main__': main()

    P1 ReplyLast reply

  • MMaster_Shredder

    @Pl45m4 said in Wie kann ich Widgets ansprechen(pyside6)?:

    Hi @Master_Shredder, willkommen im Forum,

    Hi, Dankeschön

    @Pl45m4 said in Wie kann ich Widgets ansprechen(pyside6)?:

    Ein Click worauf? Ein clicked() Signal muss ja irgendwoher kommen. Was genau soll geklickt werden? Sehe bei dir nämlich keinen Button.

    Ja ein Button.

    @Pl45m4 said in Wie kann ich Widgets ansprechen(pyside6)?:

    Der QUiLoader gibt ein QWidget zurück, welches aus der geladenen *.ui Datei erstellt wurde.
    Damit kannst du dann weiter arbeiten, die Sub-Widgets herausladen und dann die Signale verbinden.

    Ah ja so etwas habe ich mir schon gedacht, hatte auch schon mal ein Beispiel gesehen.

    @Pl45m4 said in Wie kann ich Widgets ansprechen(pyside6)?:

    Ich würde übrigens das Laden der UI File in den Konstruktor deiner Verbrauchsrechner-Klasse schieben und nicht unbedingt in der Main machen. So kannst du dann auch direkt das geladene Widget window als Klassenvariable nutzen und hast dann mit self.window Zugriff darauf (siehe oben wie in meinem Code)...

    Ja dies halte ich auch für eine gute Idee, habe es auch so umgesetzt.

    Jetzt habe ich nur das Problem, dass ich diese Fehlermeldungen hier bekomme:

    Unresolved attribute reference 'clicked' for class 'object'
    Unresolved attribute reference 'berechne' for class 'Verbrauchsrechner'

    import sysfrom PySide6 import QtWidgetsfrom PySide6.QtUiTools import QUiLoaderfrom PySide6.QtWidgets import QApplicationfrom PySide6.QtCore import QFile, QIODevicefrom Abrechnung import Abrechnungclass Verbrauchsrechner: """Main Klasse hier startet das Programm""" def __init__(self): ui_file_name = "GUI/verbrauchsrechner_gui.ui" ui_file = QFile(ui_file_name) if not ui_file.open(QIODevice.ReadOnly): print(f"Cannot open {ui_file_name}: {ui_file.errorString()}") sys.exit(-1) loader = QUiLoader() window = loader.load(ui_file) ui_file.close() if not window: print(loader.errorString()) sys.exit(-1) window.show() # Slot eingerichtet button = window.findChild(QtWidgets.QPushButton, "button_OK") button.clicked.connect(self.berechne)def berechne(self): eingegebener_zaehlerstand = self.window.spin_box_eingabe.value() abrechnung = Abrechnung.eingabe_zaehlerstand(eingegebener_zaehlerstand) self.window.arbeitspreis_netto.setText(f"{abrechnung.arbeitspreis_netto:.2f} €") self.window.arbeitspreis_brutto.setText(f"{abrechnung.arbeitspreis_brutto:.2f} €") self.window.grundpreis_netto.setText(f"{abrechnung.grundpreis_tagesgenau_netto:.2f} €") self.window.grundpreis_brutto.setText(f"{abrechnung.grundpreis_tagesgenau_brutto:.2f} €") self.window.gesamtpreis_netto.setText(f"{abrechnung.gesamtbetrag_netto:.2f} €") self.window.gesamtpreis_brutto.setText(f"{abrechnung.gesamtbetrag_brutto:.2f} €") self.window.abschlag_bis_jetzt.setText(f"{abrechnung.bisheriger_gezahlter_abschlag:.2f} €") self.window.abschlag_ende_des_jahres.setText(f"{abrechnung.abschlag_ende_des_jahres:.2f} €") self.window.gp_abz_abschlag_bj.setText(f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag:.2f} €") self.window.gp_abz_abschlag_ej.setText(f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag_ende_des_jahres:.2f}")def main(): app = QApplication(sys.argv) sys.exit(app.exec())if __name__ == '__main__': main()

    POnline

    POnline

    Pl45m4

    wrote on last edited by Pl45m4

    #4

    @Master_Shredder said in Wie kann ich Widgets ansprechen(pyside6)?:

    from PySide6.QtWidgets import QApplication

    Ändere die Zeile zu:

     from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton

    Du musst natürlich die Klassen aus den Modulen, die du explizit nutzen willst, auch einbinden
    (QSpinBox und alle anderen QWidgets, die du im weiteren Verlauf nutzt, auch)

    Unresolved attribute reference 'berechne' for class 'Verbrauchsrechner'

    Entweder ist die Meldung mit der obigen Änderung dann auch weg oder er findet deine berechne Methode nicht.
    Könnte sein, dass sie falsch eingerückt ist und er sie nicht innerhalb der Klasse findet, oder so.

    Edit:

    Vor window und button fehlt das self damit es keine lokale Variable bleibt und du self.window in der berechne Methode aufrufen kannst.

    If debugging is the process of removing software bugs, then programming must be the process of putting them in.

    ~E. W. Dijkstra

    M1 ReplyLast reply

  • PPl45m4

    @Master_Shredder said in Wie kann ich Widgets ansprechen(pyside6)?:

    from PySide6.QtWidgets import QApplication

    Ändere die Zeile zu:

     from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton

    Du musst natürlich die Klassen aus den Modulen, die du explizit nutzen willst, auch einbinden
    (QSpinBox und alle anderen QWidgets, die du im weiteren Verlauf nutzt, auch)

    Unresolved attribute reference 'berechne' for class 'Verbrauchsrechner'

    Entweder ist die Meldung mit der obigen Änderung dann auch weg oder er findet deine berechne Methode nicht.
    Könnte sein, dass sie falsch eingerückt ist und er sie nicht innerhalb der Klasse findet, oder so.

    Edit:

    Vor window und button fehlt das self damit es keine lokale Variable bleibt und du self.window in der berechne Methode aufrufen kannst.

    MOffline

    MOffline

    Master_Shredder

    wrote on last edited by

    #5

    @Pl45m4 said in Wie kann ich Widgets ansprechen(pyside6)?:

    Könnte sein, dass sie falsch eingerückt ist und er sie nicht innerhalb der Klasse findet, oder so.

    Die Einrücken dürfte eh falsch sein. Da sie ja nicht in der Klasse liegt. Ich habe dies korrigiert.

    berechne() wird nun gefunden. Dann habe ich "self" vor die initialisierung von "window" und "button" gesetzt.

    Jetzt werden wie widgets in berechne() nicht mehr gefunden.
    Cannot find reference 'spin_box_eingabe' in 'QWidget | QWidget'
    Cannot find reference 'arbeitspreis_netto' in 'QWidget | QWidget'
    Cannot find reference 'arbeitspreis_brutto' in 'QWidget | QWidget'
    ...

    Diese müssten doch jetzt bei "window" aufgerufen werden.?

    Dann habe ich noch die Widgets einzeln, in die Import Anweisung eingefügt.

    from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QLabel, QSpinBox, QDialog

    Doch diese werden leider nicht benutzt.

    Unused import statement 'QPushButton'
    Unused import statement 'QLabel'
    ...

    Dabei ist mir noch aufgefallen, dass mein Hauptfenster ein QDialog und kein QMainWindow ist.

    clicked() wird leider immer noch nicht gefunden.
    Unresolved attribute reference 'clicked' for class 'object'

    import sysfrom PySide6 import QtWidgetsfrom PySide6.QtCore import QFile, QIODevicefrom PySide6.QtUiTools import QUiLoaderfrom PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QDialog, QLabel, QSpinBoxfrom Abrechnung import Abrechnungclass Verbrauchsrechner: """Main Klasse hier startet das Programm""" def __init__(self): ui_file_name = "GUI/verbrauchsrechner_gui.ui" ui_file = QFile(ui_file_name) if not ui_file.open(QIODevice.ReadOnly): print(f"Cannot open {ui_file_name}: {ui_file.errorString()}") sys.exit(-1) loader = QUiLoader() self.window = loader.load(ui_file) ui_file.close() if not self.window: print(loader.errorString()) sys.exit(-1) self.window.show() # Slot eingerichtet self.button = self.window.findChild(QtWidgets.QPushButton, "button_OK") self.button.clicked.connect(self.berechne) def berechne(self): eingegebener_zaehlerstand = self.window.spin_box_eingabe.value() abrechnung = Abrechnung.eingabe_zaehlerstand(eingegebener_zaehlerstand) self.window.arbeitspreis_netto.setText(f"{abrechnung.arbeitspreis_netto:.2f} €") self.window.arbeitspreis_brutto.setText( f"{abrechnung.arbeitspreis_brutto:.2f} €" ) self.window.grundpreis_netto.setText( f"{abrechnung.grundpreis_tagesgenau_netto:.2f} €" ) self.window.grundpreis_brutto.setText( f"{abrechnung.grundpreis_tagesgenau_brutto:.2f} €" ) self.window.gesamtpreis_netto.setText(f"{abrechnung.gesamtbetrag_netto:.2f} €") self.window.gesamtpreis_brutto.setText( f"{abrechnung.gesamtbetrag_brutto:.2f} €" ) self.window.abschlag_bis_jetzt.setText( f"{abrechnung.bisheriger_gezahlter_abschlag:.2f} €" ) self.window.abschlag_ende_des_jahres.setText( f"{abrechnung.abschlag_ende_des_jahres:.2f} €" ) self.window.gp_abz_abschlag_bj.setText( f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag:.2f} €" ) self.window.gp_abz_abschlag_ej.setText( f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag_ende_des_jahres:.2f}" )def main(): app = QApplication(sys.argv) sys.exit(app.exec())if __name__ == "__main__": main()

    P1 ReplyLast reply

  • MMaster_Shredder

    @Pl45m4 said in Wie kann ich Widgets ansprechen(pyside6)?:

    Könnte sein, dass sie falsch eingerückt ist und er sie nicht innerhalb der Klasse findet, oder so.

    Die Einrücken dürfte eh falsch sein. Da sie ja nicht in der Klasse liegt. Ich habe dies korrigiert.

    berechne() wird nun gefunden. Dann habe ich "self" vor die initialisierung von "window" und "button" gesetzt.

    Jetzt werden wie widgets in berechne() nicht mehr gefunden.
    Cannot find reference 'spin_box_eingabe' in 'QWidget | QWidget'
    Cannot find reference 'arbeitspreis_netto' in 'QWidget | QWidget'
    Cannot find reference 'arbeitspreis_brutto' in 'QWidget | QWidget'
    ...

    Diese müssten doch jetzt bei "window" aufgerufen werden.?

    Dann habe ich noch die Widgets einzeln, in die Import Anweisung eingefügt.

    from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QLabel, QSpinBox, QDialog

    Doch diese werden leider nicht benutzt.

    Unused import statement 'QPushButton'
    Unused import statement 'QLabel'
    ...

    Dabei ist mir noch aufgefallen, dass mein Hauptfenster ein QDialog und kein QMainWindow ist.

    clicked() wird leider immer noch nicht gefunden.
    Unresolved attribute reference 'clicked' for class 'object'

    import sysfrom PySide6 import QtWidgetsfrom PySide6.QtCore import QFile, QIODevicefrom PySide6.QtUiTools import QUiLoaderfrom PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QDialog, QLabel, QSpinBoxfrom Abrechnung import Abrechnungclass Verbrauchsrechner: """Main Klasse hier startet das Programm""" def __init__(self): ui_file_name = "GUI/verbrauchsrechner_gui.ui" ui_file = QFile(ui_file_name) if not ui_file.open(QIODevice.ReadOnly): print(f"Cannot open {ui_file_name}: {ui_file.errorString()}") sys.exit(-1) loader = QUiLoader() self.window = loader.load(ui_file) ui_file.close() if not self.window: print(loader.errorString()) sys.exit(-1) self.window.show() # Slot eingerichtet self.button = self.window.findChild(QtWidgets.QPushButton, "button_OK") self.button.clicked.connect(self.berechne) def berechne(self): eingegebener_zaehlerstand = self.window.spin_box_eingabe.value() abrechnung = Abrechnung.eingabe_zaehlerstand(eingegebener_zaehlerstand) self.window.arbeitspreis_netto.setText(f"{abrechnung.arbeitspreis_netto:.2f} €") self.window.arbeitspreis_brutto.setText( f"{abrechnung.arbeitspreis_brutto:.2f} €" ) self.window.grundpreis_netto.setText( f"{abrechnung.grundpreis_tagesgenau_netto:.2f} €" ) self.window.grundpreis_brutto.setText( f"{abrechnung.grundpreis_tagesgenau_brutto:.2f} €" ) self.window.gesamtpreis_netto.setText(f"{abrechnung.gesamtbetrag_netto:.2f} €") self.window.gesamtpreis_brutto.setText( f"{abrechnung.gesamtbetrag_brutto:.2f} €" ) self.window.abschlag_bis_jetzt.setText( f"{abrechnung.bisheriger_gezahlter_abschlag:.2f} €" ) self.window.abschlag_ende_des_jahres.setText( f"{abrechnung.abschlag_ende_des_jahres:.2f} €" ) self.window.gp_abz_abschlag_bj.setText( f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag:.2f} €" ) self.window.gp_abz_abschlag_ej.setText( f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag_ende_des_jahres:.2f}" )def main(): app = QApplication(sys.argv) sys.exit(app.exec())if __name__ == "__main__": main()

    POnline

    POnline

    Pl45m4

    wrote on last edited by Pl45m4

    #6

    @Master_Shredder said in Wie kann ich Widgets ansprechen(pyside6)?:

    berechne() wird nun gefunden. Dann habe ich "self" vor die initialisierung von "window" und "button" gesetzt.

    Jetzt werden wie widgets in berechne() nicht mehr gefunden.
    Cannot find reference 'spin_box_eingabe' in 'QWidget | QWidget'
    Cannot find reference 'arbeitspreis_netto' in 'QWidget | QWidget'
    Cannot find reference 'arbeitspreis_brutto' in 'QWidget | QWidget'
    ...

    Diese müssten doch jetzt bei "window" aufgerufen werden.?

    Puh, im Prinzip schon.
    Kann es leider nicht ausprobieren und testen, da ich aktuell kein PySide nutze bzw. installiert habe.

    Deine ganze Struktur der Python Klasse(n) scheint noch nicht so ganz optimal zu sein.

    [ Edit:
    Hier gilt dasselbe wie beim Button. Du kannst nicht mehr direkt auf die Elemente zugreifen, da du window mit dem QUiLoader als ganzes QWidget aus deiner UI Datei lädst.
    D.h. du müsstest wieder für jedes Element einmal mit findChild den QObject-Eltern-Kind-"Baum" nach dem Widget mit dem Objektnamen durchsuchen.
    Da ich annehme dass das alles QLabel sind, kannst du auch alle auf einmal als Liste abfragen ]

    self.label_list = self.window.findChildren(QtWidgets.QLabel)

    Dann habe ich noch die Widgets einzeln, in die Import Anweisung eingefügt.

    from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QLabel, QSpinBox, QDialog

    Doch diese werden leider nicht benutzt.

    Unused import statement 'QPushButton'
    Unused import statement 'QLabel'
    ...

    Die unused Warnings kann man ignorieren. Die sollten weggehen sobald du die Widgets wirklich ansprichst (auf das Label oder den Button zugreifst).

    Dabei ist mir noch aufgefallen, dass mein Hauptfenster ein QDialog und kein QMainWindow ist.

    Also das Widget, was du im QtDesigner als GUI erstellt hast, ist ein QDialog und darin sind dann deine Layouts mit Textfeldern, Labels, der SpinBox und dem Button?!
    Warum ein QDialog?!
    Ist jetzt nicht "verboten", ist aber ungewöhnlich.
    Wenn du kein QMainWindow mit dem ganzen ToolBar- und MenuBar-Schnickschnack brauchst/willst, kannst du auch einfach ein QWidget als Basisklasse wählen... QDialog und QMainWindow sind im Grunde auch nichts anderes als etwas speziellere Widgets.

    clicked() wird leider immer noch nicht gefunden.
    Unresolved attribute reference 'clicked' for class 'object'

    Funktioniert denn die Zeile?

     self.button = self.window.findChild(QtWidgets.QPushButton, "button_OK")

    Ist der ObjectName korrekt und existiert in der verbrauchsrechner_gui.ui Datei ein QPushButton IN dem QDialog dort, der button_OK heißt?

    Nur um sicherzugehen:
    Ist das was oben steht das gesamte Programm? Oder gibt's eine andere Python Klasse mit QMainWindow oder so?
    (Ich sehe du importierst Funktionen aus einem Modul Abrechung, aber das sind dann wohl nur Hilfsfunktionen zur Berechnung der Werte die an anzeigen willst?!)
    Es fehlt ja auch in der main() sowas wie

    def main(): app = QApplication(sys.argv) verbr_rechner = Verbrauchsrechner() sys.exit(app.exec())if __name__ == "__main__": main()

    Edit:

    Das Einzige was mir sonst noch bzgl. der Connection einfällt, wäre deine Verbrauchsrechner Klasse zu einem QObject zu machen...

    class Verbrauchsrechner(QObject): def __init__(self, parent=None): super().__init__(parent)

    aber eigentlich sollte das keine Rolle spielen, da du ja die Klassenvariable self.window als eigenständiges Qt Widget (aktuell ja wohl QDialog) nutzt. Daher braucht die Klasse drumherum nichts mit Qt zu tun haben und kann ja auch Nicht-Qt Logik und Code enthalten.
    Und dein Button ist ja schließlich ein QPushButton (sollte, daher am besten checken, was das findChild wirklich zurückgibt).

    Vielleicht übersehe ich irgendwas Offensichtliches - wie gesagt, bin eher im C++ Umfeld unterwegs.

    If debugging is the process of removing software bugs, then programming must be the process of putting them in.

    ~E. W. Dijkstra

    M1 ReplyLast reply

  • PPl45m4

    @Master_Shredder said in Wie kann ich Widgets ansprechen(pyside6)?:

    berechne() wird nun gefunden. Dann habe ich "self" vor die initialisierung von "window" und "button" gesetzt.

    Jetzt werden wie widgets in berechne() nicht mehr gefunden.
    Cannot find reference 'spin_box_eingabe' in 'QWidget | QWidget'
    Cannot find reference 'arbeitspreis_netto' in 'QWidget | QWidget'
    Cannot find reference 'arbeitspreis_brutto' in 'QWidget | QWidget'
    ...

    Diese müssten doch jetzt bei "window" aufgerufen werden.?

    Puh, im Prinzip schon.
    Kann es leider nicht ausprobieren und testen, da ich aktuell kein PySide nutze bzw. installiert habe.

    Deine ganze Struktur der Python Klasse(n) scheint noch nicht so ganz optimal zu sein.

    [ Edit:
    Hier gilt dasselbe wie beim Button. Du kannst nicht mehr direkt auf die Elemente zugreifen, da du window mit dem QUiLoader als ganzes QWidget aus deiner UI Datei lädst.
    D.h. du müsstest wieder für jedes Element einmal mit findChild den QObject-Eltern-Kind-"Baum" nach dem Widget mit dem Objektnamen durchsuchen.
    Da ich annehme dass das alles QLabel sind, kannst du auch alle auf einmal als Liste abfragen ]

    self.label_list = self.window.findChildren(QtWidgets.QLabel)

    Dann habe ich noch die Widgets einzeln, in die Import Anweisung eingefügt.

    from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QLabel, QSpinBox, QDialog

    Doch diese werden leider nicht benutzt.

    Unused import statement 'QPushButton'
    Unused import statement 'QLabel'
    ...

    Die unused Warnings kann man ignorieren. Die sollten weggehen sobald du die Widgets wirklich ansprichst (auf das Label oder den Button zugreifst).

    Dabei ist mir noch aufgefallen, dass mein Hauptfenster ein QDialog und kein QMainWindow ist.

    Also das Widget, was du im QtDesigner als GUI erstellt hast, ist ein QDialog und darin sind dann deine Layouts mit Textfeldern, Labels, der SpinBox und dem Button?!
    Warum ein QDialog?!
    Ist jetzt nicht "verboten", ist aber ungewöhnlich.
    Wenn du kein QMainWindow mit dem ganzen ToolBar- und MenuBar-Schnickschnack brauchst/willst, kannst du auch einfach ein QWidget als Basisklasse wählen... QDialog und QMainWindow sind im Grunde auch nichts anderes als etwas speziellere Widgets.

    clicked() wird leider immer noch nicht gefunden.
    Unresolved attribute reference 'clicked' for class 'object'

    Funktioniert denn die Zeile?

     self.button = self.window.findChild(QtWidgets.QPushButton, "button_OK")

    Ist der ObjectName korrekt und existiert in der verbrauchsrechner_gui.ui Datei ein QPushButton IN dem QDialog dort, der button_OK heißt?

    Nur um sicherzugehen:
    Ist das was oben steht das gesamte Programm? Oder gibt's eine andere Python Klasse mit QMainWindow oder so?
    (Ich sehe du importierst Funktionen aus einem Modul Abrechung, aber das sind dann wohl nur Hilfsfunktionen zur Berechnung der Werte die an anzeigen willst?!)
    Es fehlt ja auch in der main() sowas wie

    def main(): app = QApplication(sys.argv) verbr_rechner = Verbrauchsrechner() sys.exit(app.exec())if __name__ == "__main__": main()

    Edit:

    Das Einzige was mir sonst noch bzgl. der Connection einfällt, wäre deine Verbrauchsrechner Klasse zu einem QObject zu machen...

    class Verbrauchsrechner(QObject): def __init__(self, parent=None): super().__init__(parent)

    aber eigentlich sollte das keine Rolle spielen, da du ja die Klassenvariable self.window als eigenständiges Qt Widget (aktuell ja wohl QDialog) nutzt. Daher braucht die Klasse drumherum nichts mit Qt zu tun haben und kann ja auch Nicht-Qt Logik und Code enthalten.
    Und dein Button ist ja schließlich ein QPushButton (sollte, daher am besten checken, was das findChild wirklich zurückgibt).

    Vielleicht übersehe ich irgendwas Offensichtliches - wie gesagt, bin eher im C++ Umfeld unterwegs.

    MOffline

    MOffline

    Master_Shredder

    wrote on last edited by

    #7

    Danke für die ausführliche Antwort.

    Da ich annehme dass das alles QLabel sind, kannst du auch alle auf einmal als Liste abfragen

    Ja, dies sieht schön Elegant aus. Aber wie greife ich denn dann auf die einzelnen Label zu? Mit Index [0]... wird dies sehr unübersichtlich, unsauber.

    Also das Widget, was du im QtDesigner als GUI erstellt hast, ist ein QDialog und darin sind dann deine Layouts mit Textfeldern, Labels, der SpinBox und dem Button?!

    Ja genau.

    Warum ein QDialog?!
    Ist jetzt nicht "verboten", ist aber ungewöhnlich.
    Wenn du kein QMainWindow mit dem ganzen ToolBar- und MenuBar-Schnickschnack brauchst/willst, kannst du auch einfach ein QWidget als Basisklasse wählen... QDialog und QMainWindow sind im Grunde auch nichts anderes als etwas speziellere Widgets.

    Dies kam durch ein Tutorial. Als ich das Erste mal Pyside benutzt habe wurde dies so erklärt. Und da dies ein Fenster und ein Button enthielt, so wie ich es brauchte, habe ich es gerade behalten. Für Zukunft's sicher zu sein würde ich auch ein QMainWindow holen. Nur am Anfang wusste ich auch nicht, dass ich die Menübar einfach entfernen kann.
    Wenn es jetzt nichts an der Syntax ändert, würde ich den QDialog jetzt auch noch so lassen.

    Funktioniert denn die Zeile?

    self.button = self.window.findChild(QtWidgets.QPushButton, "button_OK")

    Ist der ObjectName korrekt und existiert in der verbrauchsrechner_gui.ui Datei ein QPushButton IN dem QDialog dort, der button_OK heißt?

    Ob sie "funktioniert" ist schwer zu sagen. Da das Argument mit dem gesucht wird ein String ist funktioniert die Fehleranzeige von PyCharm nicht. Bzw. der Fehler hängt bei clicked().

    Unresolved attribute reference 'clicked' for class 'object'

    Aber bei den Versuchen in berechne() einmal um die SpinBox anzusprechen und einmal das Label zu setten bekomme ich Fehler.

    Unresolved attribute reference 'spin_box_eingabe' for class 'object'
    Unresolved attribute reference 'setText' for class 'object'

    Ja der ObjektName ist korrekt.

    Ist das was oben steht das gesamte Programm? Oder gibt's eine andere Python Klasse mit QMainWindow oder so?
    (Ich sehe du importierst Funktionen aus einem Modul Abrechung, aber das sind dann wohl nur Hilfsfunktionen zur Berechnung der Werte die an anzeigen willst?!)

    Ja genau. In Abrechnung sind nur Hilfsfunktionen zur Berechnung.

    Es fehlt ja auch in der main() sowas wie

    Ja da bin ich auch schon drauf gekommen. Habe ein Objekt der Klasse erstellt und darüber dann auch "window" anzeigen lassen.
    Nun startet meine GUI auch!

    Wenn ich einen Wert zum berechnen angebe und den Button betätige erhalte ich diese Fehlermeldung:

    Attribute Qt::AA_ShareOpenGLContexts must be set before QCoreApplication is created.Traceback (most recent call last): File "/home/masterblack/PycharmProjects/Verbrauchsrechner/Verbrauchsrechner.py", line 38, in berechne eingegebener_zaehlerstand = spin_box.spin_box_eingabe.value() ^^^^^^^^^^^^^^^^^^^^^^^^^AttributeError: 'PySide6.QtWidgets.QSpinBox' object has no attribute 'spin_box_eingabe'Process finished with exit code 0

    Hier der neue Quelltext:

    import sysfrom PySide6 import QtWidgetsfrom PySide6.QtCore import QFile, QIODevicefrom PySide6.QtUiTools import QUiLoaderfrom PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QDialog, QLabel, QSpinBox, QWidgetfrom Abrechnung import Abrechnungclass Verbrauchsrechner: """Main Klasse hier startet das Programm""" def __init__(self): ui_file_name = "GUI/verbrauchsrechner_gui.ui" ui_file = QFile(ui_file_name) if not ui_file.open(QIODevice.ReadOnly): print(f"Cannot open {ui_file_name}: {ui_file.errorString()}") sys.exit(-1) loader = QUiLoader() self.window = loader.load(ui_file) ui_file.close() if not self.window: print(loader.errorString()) sys.exit(-1) # window.show() # Slot eingerichtet self.button = self.window.findChild(QtWidgets.QPushButton, "button_OK") self.button.clicked.connect(self.berechne) # self.label_list = self.window.findChildren(QtWidgets.QLabel) def berechne(self): spin_box = self.window.findChild(QtWidgets.QSpinBox, "spin_box_eingabe") eingegebener_zaehlerstand = spin_box.spin_box_eingabe.value() abrechnung = Abrechnung.eingabe_zaehlerstand(eingegebener_zaehlerstand) arbeitspreis_netto = self.window.findChild(QtWidgets.QLabel, "arbeitspreis_netto") arbeitspreis_netto.setText(f"{abrechnung.arbeitspreis_netto:.2f} €") self.window.arbeitspreis_brutto.setText( f"{abrechnung.arbeitspreis_brutto:.2f} €" ) self.window.grundpreis_netto.setText( f"{abrechnung.grundpreis_tagesgenau_netto:.2f} €" ) self.window.grundpreis_brutto.setText( f"{abrechnung.grundpreis_tagesgenau_brutto:.2f} €" ) self.window.gesamtpreis_netto.setText(f"{abrechnung.gesamtbetrag_netto:.2f} €") self.window.gesamtpreis_brutto.setText( f"{abrechnung.gesamtbetrag_brutto:.2f} €" ) self.window.abschlag_bis_jetzt.setText( f"{abrechnung.bisheriger_gezahlter_abschlag:.2f} €" ) self.window.abschlag_ende_des_jahres.setText( f"{abrechnung.abschlag_ende_des_jahres:.2f} €" ) self.window.gp_abz_abschlag_bj.setText( f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag:.2f} €" ) self.window.gp_abz_abschlag_ej.setText( f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag_ende_des_jahres:.2f}" )def main(): app = QApplication(sys.argv) verbrauchsrechner = Verbrauchsrechner() verbrauchsrechner.window.show() sys.exit(app.exec())if __name__ == "__main__": main()

    Daher braucht die Klasse drumherum nichts mit Qt zu tun haben und kann ja auch Nicht-Qt Logik und Code enthalten.
    Ja, so weit Ich dies beurteilen kann, denke ich auch so.

    Vielleicht übersehe ich irgendwas Offensichtliches - wie gesagt, bin eher im C++ Umfeld unterwegs.

    Schon gut ; )

    P1 ReplyLast reply

  • MMaster_Shredder

    Danke für die ausführliche Antwort.

    Da ich annehme dass das alles QLabel sind, kannst du auch alle auf einmal als Liste abfragen

    Ja, dies sieht schön Elegant aus. Aber wie greife ich denn dann auf die einzelnen Label zu? Mit Index [0]... wird dies sehr unübersichtlich, unsauber.

    Also das Widget, was du im QtDesigner als GUI erstellt hast, ist ein QDialog und darin sind dann deine Layouts mit Textfeldern, Labels, der SpinBox und dem Button?!

    Ja genau.

    Warum ein QDialog?!
    Ist jetzt nicht "verboten", ist aber ungewöhnlich.
    Wenn du kein QMainWindow mit dem ganzen ToolBar- und MenuBar-Schnickschnack brauchst/willst, kannst du auch einfach ein QWidget als Basisklasse wählen... QDialog und QMainWindow sind im Grunde auch nichts anderes als etwas speziellere Widgets.

    Dies kam durch ein Tutorial. Als ich das Erste mal Pyside benutzt habe wurde dies so erklärt. Und da dies ein Fenster und ein Button enthielt, so wie ich es brauchte, habe ich es gerade behalten. Für Zukunft's sicher zu sein würde ich auch ein QMainWindow holen. Nur am Anfang wusste ich auch nicht, dass ich die Menübar einfach entfernen kann.
    Wenn es jetzt nichts an der Syntax ändert, würde ich den QDialog jetzt auch noch so lassen.

    Funktioniert denn die Zeile?

    self.button = self.window.findChild(QtWidgets.QPushButton, "button_OK")

    Ist der ObjectName korrekt und existiert in der verbrauchsrechner_gui.ui Datei ein QPushButton IN dem QDialog dort, der button_OK heißt?

    Ob sie "funktioniert" ist schwer zu sagen. Da das Argument mit dem gesucht wird ein String ist funktioniert die Fehleranzeige von PyCharm nicht. Bzw. der Fehler hängt bei clicked().

    Unresolved attribute reference 'clicked' for class 'object'

    Aber bei den Versuchen in berechne() einmal um die SpinBox anzusprechen und einmal das Label zu setten bekomme ich Fehler.

    Unresolved attribute reference 'spin_box_eingabe' for class 'object'
    Unresolved attribute reference 'setText' for class 'object'

    Ja der ObjektName ist korrekt.

    Ist das was oben steht das gesamte Programm? Oder gibt's eine andere Python Klasse mit QMainWindow oder so?
    (Ich sehe du importierst Funktionen aus einem Modul Abrechung, aber das sind dann wohl nur Hilfsfunktionen zur Berechnung der Werte die an anzeigen willst?!)

    Ja genau. In Abrechnung sind nur Hilfsfunktionen zur Berechnung.

    Es fehlt ja auch in der main() sowas wie

    Ja da bin ich auch schon drauf gekommen. Habe ein Objekt der Klasse erstellt und darüber dann auch "window" anzeigen lassen.
    Nun startet meine GUI auch!

    Wenn ich einen Wert zum berechnen angebe und den Button betätige erhalte ich diese Fehlermeldung:

    Attribute Qt::AA_ShareOpenGLContexts must be set before QCoreApplication is created.Traceback (most recent call last): File "/home/masterblack/PycharmProjects/Verbrauchsrechner/Verbrauchsrechner.py", line 38, in berechne eingegebener_zaehlerstand = spin_box.spin_box_eingabe.value() ^^^^^^^^^^^^^^^^^^^^^^^^^AttributeError: 'PySide6.QtWidgets.QSpinBox' object has no attribute 'spin_box_eingabe'Process finished with exit code 0

    Hier der neue Quelltext:

    import sysfrom PySide6 import QtWidgetsfrom PySide6.QtCore import QFile, QIODevicefrom PySide6.QtUiTools import QUiLoaderfrom PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QDialog, QLabel, QSpinBox, QWidgetfrom Abrechnung import Abrechnungclass Verbrauchsrechner: """Main Klasse hier startet das Programm""" def __init__(self): ui_file_name = "GUI/verbrauchsrechner_gui.ui" ui_file = QFile(ui_file_name) if not ui_file.open(QIODevice.ReadOnly): print(f"Cannot open {ui_file_name}: {ui_file.errorString()}") sys.exit(-1) loader = QUiLoader() self.window = loader.load(ui_file) ui_file.close() if not self.window: print(loader.errorString()) sys.exit(-1) # window.show() # Slot eingerichtet self.button = self.window.findChild(QtWidgets.QPushButton, "button_OK") self.button.clicked.connect(self.berechne) # self.label_list = self.window.findChildren(QtWidgets.QLabel) def berechne(self): spin_box = self.window.findChild(QtWidgets.QSpinBox, "spin_box_eingabe") eingegebener_zaehlerstand = spin_box.spin_box_eingabe.value() abrechnung = Abrechnung.eingabe_zaehlerstand(eingegebener_zaehlerstand) arbeitspreis_netto = self.window.findChild(QtWidgets.QLabel, "arbeitspreis_netto") arbeitspreis_netto.setText(f"{abrechnung.arbeitspreis_netto:.2f} €") self.window.arbeitspreis_brutto.setText( f"{abrechnung.arbeitspreis_brutto:.2f} €" ) self.window.grundpreis_netto.setText( f"{abrechnung.grundpreis_tagesgenau_netto:.2f} €" ) self.window.grundpreis_brutto.setText( f"{abrechnung.grundpreis_tagesgenau_brutto:.2f} €" ) self.window.gesamtpreis_netto.setText(f"{abrechnung.gesamtbetrag_netto:.2f} €") self.window.gesamtpreis_brutto.setText( f"{abrechnung.gesamtbetrag_brutto:.2f} €" ) self.window.abschlag_bis_jetzt.setText( f"{abrechnung.bisheriger_gezahlter_abschlag:.2f} €" ) self.window.abschlag_ende_des_jahres.setText( f"{abrechnung.abschlag_ende_des_jahres:.2f} €" ) self.window.gp_abz_abschlag_bj.setText( f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag:.2f} €" ) self.window.gp_abz_abschlag_ej.setText( f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag_ende_des_jahres:.2f}" )def main(): app = QApplication(sys.argv) verbrauchsrechner = Verbrauchsrechner() verbrauchsrechner.window.show() sys.exit(app.exec())if __name__ == "__main__": main()

    Daher braucht die Klasse drumherum nichts mit Qt zu tun haben und kann ja auch Nicht-Qt Logik und Code enthalten.
    Ja, so weit Ich dies beurteilen kann, denke ich auch so.

    Vielleicht übersehe ich irgendwas Offensichtliches - wie gesagt, bin eher im C++ Umfeld unterwegs.

    Schon gut ; )

    POnline

    POnline

    Pl45m4

    wrote on last edited by Pl45m4

    #8

    @Master_Shredder said in Wie kann ich Widgets ansprechen(pyside6)?:

     spin_box = self.window.findChild(QtWidgets.QSpinBox, "spin_box_eingabe") eingegebener_zaehlerstand = spin_box.spin_box_eingabe.value()

    Da spin_box ja schon deine QSpinBox (spin_box_eingabe) aus der UI Datei ist, muss die untere Zeile lauten:

     eingegebener_zaehlerstand = spin_box.value()

    Da ich annehme dass das alles QLabel sind, kannst du auch alle auf einmal als Liste abfragen

    Ja, dies sieht schön Elegant aus. Aber wie greife ich denn dann auf die einzelnen Label zu? Mit Index [0]... wird dies sehr unübersichtlich, unsauber.

    Ja sonst bleibt nur alle Widgets, die du ändern willst einzeln abzufragen und dann in der lokalen Klasse weiterzumachen.

    In Großen und Ganzen ist der Ansatz den du gewählt hast auch eher ungewöhnt bzw. etwas umständlich.
    QUiLoader wird eher für Widgets bzw. UI Files genutzt, die man "mal eben" zur Laufzeit nachladen will und wo man dann nicht mehr viel verändert. Mit dem Loader kann man ja auch einzelne Widgets bzw. Widget-Plugins aus einer Library dynamisch erstellen/laden.

    Bei Qt hast du eigentlich 3 Möglichkeiten deine GUI zu erstellen (und zu designen):

    • Über den Designer mit .ui Datei, die direkt eingebunden wird
      • bei Python muss diese zusätzlich und manuell mit dem UIC Tool in eine .py - Klasse konvertiert werden.
        QtCreator mit C++ macht dies automatisiert und wandelt die .ui mit uic in einen C-Header um... Denke mit Python würde sich das auch irgendwie automatisieren lassen (muss ja nur, wenn du Änderungen an der UI-File vornehmen willst und irgendwann ist man ja auch fertig damit)
    • mittels QUiLoader zur Laufzeit Widgets aus .ui Dateien laden
    • Ohne Designer die GUI "per Hand" erstellen (sowohl C++ als auch Python)
      • Vorteil, man lernt schneller den Umgang mit Qt, ist leider aber gerade für Anfänger nicht so simple. Dafür hat man jedes Element direkt im Code vorliegen wo man es benötigt und muss eher selten mit findChild(ren) das konstruierte Widget durchsuchen.

    Im Prinzip sind 1 und 3 die häufigsten Methoden, aber kann verstehen, dass als Python Nutzer es nervig ist, jedes Mal seine UI Datei selbst in eine py-Klasse umzuwandeln. Weshalb wohl viele Python-Beispiele zu QUiLoader existieren.
    Im C++ Umfeld wird es eher seltener genutzt.

    Hab vorhin aus eigenem Interesse mal geschaut und Beispiele für den Einsatz vom QUiLoader in Python gefunden (etwas "dynamischer" als in deinem Fall).

    Probier mal deine Klasse Verbrauchsrechner an das hier anzupassen:

    Oder mach ein neues Projekt auf und kopier den Code von dort. Wenn er immer noch nicht funktioniert, scheint irgendwas mit deiner IDE oder der PySide Installation nicht zu stimmen.

    Viel Erfolg :)

    Edit:

    Ob sie "funktioniert" ist schwer zu sagen. Da das Argument mit dem gesucht wird ein String ist funktioniert die Fehleranzeige von PyCharm nicht. Bzw. der Fehler hängt bei clicked().

    Unresolved attribute reference 'clicked' for class 'object'

    Könnte man beispielsweise so testen:
    (dann das window.show() in der main() wegkommentieren und schauen ob nur der Button aus der UI mit dem entsprechenden Text erscheint)

    self.button = self.window.findChild(QtWidgets.QPushButton, "button_OK")self.button.show()

    Zu der Klasse Verbrauchsrechner fällt mir noch ein, dass du ja im Prinzip die Member-Funktion berechne() mit dem clicked() Signal des Buttons verbinden willst... Eine Signal & Slot Verbindung funktioniert nur zwischen zwei QObject Klassen.
    Was ich vorher gesagt hatte gilt nur für die Einrichtung der Verbindung... dies muss selbst kein QObject sein, sondern mindestens Zugriff auf Sender und Empfänger haben.
    Also muss dein Verbrauchsrechner mindestens ein QObject werden, damit du den Button mit dem Slot in der Klasse verbinden kannst. Höhere Klassen sind nicht notwendig, da du die gesamte UI durch den QUiLoader lädst.
    Die Klasse Form in dem verlinkten Beispiel ist ja auch ein QObject.

    Weiß nicht, wie gut deine Python-Kenntnisse insgesamt sind, aber dazu gäbe es noch Lambdas

    z.B.

    variable = 42button.clicked.connect( lambda: self.meineButtonFunktion( variable, button ) )# oderbutton.clicked.connect( lambda: print("Hello World") )# print("Hello World") bzw. allgemein der Code der Lambda Funktion wird jedes Mal ausgeführt# wenn der Button geklickt wird,# ohne dass man eine separate Funktion/Slot benötigt

    If debugging is the process of removing software bugs, then programming must be the process of putting them in.

    ~E. W. Dijkstra

    1 ReplyLast reply

  • MOffline

    MOffline

    Master_Shredder

    wrote on last edited by

    #9

    🤦Ich musste gerade feststellen, dass das Programm in der Konstellation mit findChild() beim Button läuft!

    Das was ich angezeigt bekomme sind Warnungen. Also es ist nicht richtig aber auch nicht so falsch, dass es nicht läuft.

    import sysfrom PySide6 import QtWidgetsfrom PySide6.QtCore import QFile, QIODevicefrom PySide6.QtUiTools import QUiLoaderfrom PySide6.QtWidgets import QApplicationfrom Abrechnung import Abrechnungclass Verbrauchsrechner: """Main Klasse hier startet das Programm""" def __init__(self): ui_file_name = "GUI/verbrauchsrechner_gui.ui" ui_file = QFile(ui_file_name) if not ui_file.open(QIODevice.ReadOnly): print(f"Cannot open {ui_file_name}: {ui_file.errorString()}") sys.exit(-1) loader = QUiLoader() self.window = loader.load(ui_file) ui_file.close() if not self.window: print(loader.errorString()) sys.exit(-1) # window.show() # Slot eingerichtet self.button = self.window.findChild(QtWidgets.QPushButton, "button_OK") self.button.clicked.connect(self.berechne) def berechne(self): eingegebener_zaehlerstand = self.window.spin_box_eingabe.value() abrechnung = Abrechnung.eingabe_zaehlerstand(eingegebener_zaehlerstand) self.window.arbeitspreis_netto.setText(f"{abrechnung.arbeitspreis_netto:.2f} €") self.window.arbeitspreis_brutto.setText( f"{abrechnung.arbeitspreis_brutto:.2f} €" ) self.window.grundpreis_netto.setText( f"{abrechnung.grundpreis_tagesgenau_netto:.2f} €" ) self.window.grundpreis_brutto.setText( f"{abrechnung.grundpreis_tagesgenau_brutto:.2f} €" ) self.window.gesamtpreis_netto.setText(f"{abrechnung.gesamtbetrag_netto:.2f} €") self.window.gesamtpreis_brutto.setText( f"{abrechnung.gesamtbetrag_brutto:.2f} €" ) self.window.abschlag_bis_jetzt.setText( f"{abrechnung.bisheriger_gezahlter_abschlag:.2f} €" ) self.window.abschlag_ende_des_jahres.setText( f"{abrechnung.abschlag_ende_des_jahres:.2f} €" ) self.window.gp_abz_abschlag_bj.setText( f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag:.2f} €" ) self.window.gp_abz_abschlag_ej.setText( f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag_ende_des_jahres:.2f}" )def main(): app = QApplication(sys.argv) verbrauchsrechner = Verbrauchsrechner() verbrauchsrechner.window.show() sys.exit(app.exec())if __name__ == "__main__": main()

    Vielleicht kam es bei dir zu Verwirrung 😅.

    In Großen und Ganzen ist der Ansatz den du gewählt hast auch eher ungewöhnt bzw. etwas umständlich.
    Na gut, den hatte ich eigentlich nur gewählt, weil mal jemand in einem Python Forum meinte. Man würde es so machen.
    Ich habe auch mal im Python Forum gefragt, ob dies vielleicht aus der Python Sicht besser wäre. Nur leider habe ich da noch keine Antwort bekommen.

    Aber jetzt unter dem Gesichtspunkt, wie du es mir erklärt hast die drei Methoden.
    Erstmal zu Nr. 3. Also ich habe Qt gewählt weil ich mir das GUI bauen erleichtern wollte. Habe vorher mit TKinder(Für Python GUI's) gebaut, auch rein Code. Und ja, da wirst du ja wahnsinnig wenn du mal etwas ändern willst. Deshalb Qt-Designer.

    Also wenn jetzt nichts besonderes aus dem Python Forum oder sonst kommt.
    Dann würde ich es mit Methode Nr. 1 machen. Wirklich umständlich ist dies ja nicht. Eine Zeile auf Kommando.
    Mir ist halt schon wichtig, dass es gemacht wird wie es gemacht werden sollte!

    Ich habe dies auch mal auf einem neuen Branch angewendet. Auch mit QMainWindow statt QDialog.

    import sysfrom PySide6.QtCore import QFilefrom PySide6.QtWidgets import QApplication, QMainWindowfrom Abrechnung import Abrechnungfrom GUI.Verbrauchsrechner_gui import Ui_MainWindowclass Verbrauchsrechner(QMainWindow): """Main Klasse hier startet das Programm""" def __init__(self): super(Verbrauchsrechner, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) # Slot eingerichtet self.ui.button_OK.clicked.connect(self.berechne) # Slot def berechne(self): eingegebener_zaehlerstand = self.ui.spin_box_eingabe.value() abrechnung = Abrechnung.eingabe_zaehlerstand(eingegebener_zaehlerstand) self.ui.arbeitspreis_netto.setText(f"{abrechnung.arbeitspreis_netto:.2f} €") self.ui.arbeitspreis_brutto.setText(f"{abrechnung.arbeitspreis_brutto:.2f} €") self.ui.grundpreis_netto.setText( f"{abrechnung.grundpreis_tagesgenau_netto:.2f} €" ) self.ui.grundpreis_brutto.setText( f"{abrechnung.grundpreis_tagesgenau_brutto:.2f} €" ) self.ui.gesamtpreis_netto.setText(f"{abrechnung.gesamtbetrag_netto:.2f} €") self.ui.gesamtpreis_brutto.setText(f"{abrechnung.gesamtbetrag_brutto:.2f} €") self.ui.abschlag_bis_jetzt.setText( f"{abrechnung.bisheriger_gezahlter_abschlag:.2f} €" ) self.ui.abschlag_ende_des_jahres.setText( f"{abrechnung.abschlag_ende_des_jahres:.2f} €" ) self.ui.gp_abz_abschlag_bj.setText( f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag:.2f} €" ) self.ui.gp_abz_abschlag_ej.setText( f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag_ende_des_jahres:.2f}" )def main(): # eintrag_einfuegen() app = QApplication(sys.argv) window = Verbrauchsrechner() window.show() sys.exit(app.exec())if __name__ == "__main__": main()

    Funktioniert, sichtlich, wunderbar.

    P1 ReplyLast reply

  • MOffline

    MOffline

    Master_Shredder

    wrote on last edited by

    #10

    Hi @Pl45m4 ,

    ich habe eine Antwort aus dem Python Forum bekommen. Glücklicher weiße auch von dem der dies mal, mit direkt laden, erwähnte.

    "Ich nehme die *.uic-Dateien, weil Quelltext generieren ein unnötiger Zwischenschritt ist, und sich dann auch das Problem nicht stellt generierte Dateien in der Versionsverwaltung zu haben oder nicht.

    Gegen die Warnungen kannst Du nicht wirklich was machen, ausser sie komplett abschalten. Damit muss man bei dynamischen Programmiersprachen halt leben das es Grenzen bei der statischen Analyse von Quelltext gibt."

    Ich würde es dann nach der von dir erwähnten Methode Nr. 1 machen. Da es für mich, aus der Sicht von Python, keinen Sinnvollen Grund gibt es anders zu machen. Und außerdem kenne ich mich auch nicht so gut aus, dass ich selbst entscheiden könnte ob die Warnungen zu ignorieren sind.

    Ja, dies habe ich in dem Post obendrüber ja schon umgesetzt. Kann ich dies so lassen, oder gibt es verbesserung's Vorschläge?

    1 ReplyLast reply

  • MMaster_Shredder

    🤦Ich musste gerade feststellen, dass das Programm in der Konstellation mit findChild() beim Button läuft!

    Das was ich angezeigt bekomme sind Warnungen. Also es ist nicht richtig aber auch nicht so falsch, dass es nicht läuft.

    import sysfrom PySide6 import QtWidgetsfrom PySide6.QtCore import QFile, QIODevicefrom PySide6.QtUiTools import QUiLoaderfrom PySide6.QtWidgets import QApplicationfrom Abrechnung import Abrechnungclass Verbrauchsrechner: """Main Klasse hier startet das Programm""" def __init__(self): ui_file_name = "GUI/verbrauchsrechner_gui.ui" ui_file = QFile(ui_file_name) if not ui_file.open(QIODevice.ReadOnly): print(f"Cannot open {ui_file_name}: {ui_file.errorString()}") sys.exit(-1) loader = QUiLoader() self.window = loader.load(ui_file) ui_file.close() if not self.window: print(loader.errorString()) sys.exit(-1) # window.show() # Slot eingerichtet self.button = self.window.findChild(QtWidgets.QPushButton, "button_OK") self.button.clicked.connect(self.berechne) def berechne(self): eingegebener_zaehlerstand = self.window.spin_box_eingabe.value() abrechnung = Abrechnung.eingabe_zaehlerstand(eingegebener_zaehlerstand) self.window.arbeitspreis_netto.setText(f"{abrechnung.arbeitspreis_netto:.2f} €") self.window.arbeitspreis_brutto.setText( f"{abrechnung.arbeitspreis_brutto:.2f} €" ) self.window.grundpreis_netto.setText( f"{abrechnung.grundpreis_tagesgenau_netto:.2f} €" ) self.window.grundpreis_brutto.setText( f"{abrechnung.grundpreis_tagesgenau_brutto:.2f} €" ) self.window.gesamtpreis_netto.setText(f"{abrechnung.gesamtbetrag_netto:.2f} €") self.window.gesamtpreis_brutto.setText( f"{abrechnung.gesamtbetrag_brutto:.2f} €" ) self.window.abschlag_bis_jetzt.setText( f"{abrechnung.bisheriger_gezahlter_abschlag:.2f} €" ) self.window.abschlag_ende_des_jahres.setText( f"{abrechnung.abschlag_ende_des_jahres:.2f} €" ) self.window.gp_abz_abschlag_bj.setText( f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag:.2f} €" ) self.window.gp_abz_abschlag_ej.setText( f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag_ende_des_jahres:.2f}" )def main(): app = QApplication(sys.argv) verbrauchsrechner = Verbrauchsrechner() verbrauchsrechner.window.show() sys.exit(app.exec())if __name__ == "__main__": main()

    Vielleicht kam es bei dir zu Verwirrung 😅.

    In Großen und Ganzen ist der Ansatz den du gewählt hast auch eher ungewöhnt bzw. etwas umständlich.
    Na gut, den hatte ich eigentlich nur gewählt, weil mal jemand in einem Python Forum meinte. Man würde es so machen.
    Ich habe auch mal im Python Forum gefragt, ob dies vielleicht aus der Python Sicht besser wäre. Nur leider habe ich da noch keine Antwort bekommen.

    Aber jetzt unter dem Gesichtspunkt, wie du es mir erklärt hast die drei Methoden.
    Erstmal zu Nr. 3. Also ich habe Qt gewählt weil ich mir das GUI bauen erleichtern wollte. Habe vorher mit TKinder(Für Python GUI's) gebaut, auch rein Code. Und ja, da wirst du ja wahnsinnig wenn du mal etwas ändern willst. Deshalb Qt-Designer.

    Also wenn jetzt nichts besonderes aus dem Python Forum oder sonst kommt.
    Dann würde ich es mit Methode Nr. 1 machen. Wirklich umständlich ist dies ja nicht. Eine Zeile auf Kommando.
    Mir ist halt schon wichtig, dass es gemacht wird wie es gemacht werden sollte!

    Ich habe dies auch mal auf einem neuen Branch angewendet. Auch mit QMainWindow statt QDialog.

    import sysfrom PySide6.QtCore import QFilefrom PySide6.QtWidgets import QApplication, QMainWindowfrom Abrechnung import Abrechnungfrom GUI.Verbrauchsrechner_gui import Ui_MainWindowclass Verbrauchsrechner(QMainWindow): """Main Klasse hier startet das Programm""" def __init__(self): super(Verbrauchsrechner, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) # Slot eingerichtet self.ui.button_OK.clicked.connect(self.berechne) # Slot def berechne(self): eingegebener_zaehlerstand = self.ui.spin_box_eingabe.value() abrechnung = Abrechnung.eingabe_zaehlerstand(eingegebener_zaehlerstand) self.ui.arbeitspreis_netto.setText(f"{abrechnung.arbeitspreis_netto:.2f} €") self.ui.arbeitspreis_brutto.setText(f"{abrechnung.arbeitspreis_brutto:.2f} €") self.ui.grundpreis_netto.setText( f"{abrechnung.grundpreis_tagesgenau_netto:.2f} €" ) self.ui.grundpreis_brutto.setText( f"{abrechnung.grundpreis_tagesgenau_brutto:.2f} €" ) self.ui.gesamtpreis_netto.setText(f"{abrechnung.gesamtbetrag_netto:.2f} €") self.ui.gesamtpreis_brutto.setText(f"{abrechnung.gesamtbetrag_brutto:.2f} €") self.ui.abschlag_bis_jetzt.setText( f"{abrechnung.bisheriger_gezahlter_abschlag:.2f} €" ) self.ui.abschlag_ende_des_jahres.setText( f"{abrechnung.abschlag_ende_des_jahres:.2f} €" ) self.ui.gp_abz_abschlag_bj.setText( f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag:.2f} €" ) self.ui.gp_abz_abschlag_ej.setText( f"{abrechnung.aktuelle_kosten_abz_bisheriger_abschlag_ende_des_jahres:.2f}" )def main(): # eintrag_einfuegen() app = QApplication(sys.argv) window = Verbrauchsrechner() window.show() sys.exit(app.exec())if __name__ == "__main__": main()

    Funktioniert, sichtlich, wunderbar.

    POnline

    POnline

    Pl45m4

    wrote on last edited by Pl45m4

    #11

    @Master_Shredder said in Wie kann ich Widgets ansprechen(pyside6)?:

    🤦Ich musste gerade feststellen, dass das Programm in der Konstellation mit findChild() beim Button läuft!

    Haha ok, gut zu hören.

    Vielleicht kam es bei dir zu Verwirrung 😅.

    Ja weil ich mir nicht mehr sicher war wie es in Python funktioniert mit der Verbindung. Ob die Klasse, wo eine Funktion mit einem Signal verbunden ist, ein QObject sein muss oder nicht (in C++ kann man nur QObject Klassen direkt verbinden).
    Anscheinend muss es in PySide nicht so sein...

    Funktioniert, sichtlich, wunderbar.

    Ja das ist einer der "empfohlenen Wege", wie man den QtDesigner nutzt. Ob man es so macht, ist ja jedem selbst überlassen.

    @Master_Shredder said in Wie kann ich Widgets ansprechen(pyside6)?:

    "Ich nehme die *.uic-Dateien, weil Quelltext generieren ein unnötiger Zwischenschritt ist, und sich dann auch das Problem nicht stellt generierte Dateien in der Versionsverwaltung zu haben oder nicht.

    Gegen die Warnungen kannst Du nicht wirklich was machen, ausser sie komplett abschalten. Damit muss man bei dynamischen Programmiersprachen halt leben das es Grenzen bei der statischen Analyse von Quelltext gibt."

    Die Verwendung vom Designer macht den Code bzw. Anwendung etwas schwerer zu debuggen und für Dritte zu verstehen.
    Deswegen wird in professionellen QtWidget-Apps meist kein Designer genutzt (QML/QtDesign Studio ist nochmal eine andere Geschichte). Gerade weil man irgendwann sehr limitiert ist, in dem was man tun/umsetzen kann. Daher ist man dann zwangsläufig auf eine (unübersichtliche) Hybrid-Lösung angewiesen.
    Aus dem Grund verzichten viele eher komplett auf den QtDesigner und die .ui Dateien und schreiben ihre GUI selbst. Resultiert dann zwar in mehr Code, ist aber übersichtlicher. Da sieht dann jeder Leser von dem Code direkt was er bekommt (zu erwarten hat) und muss nicht noch irgendwelche XML Blöcke oder automatisch generierte Dateien durchsuchen.

    Auch wenn du sagst, dass es dir aufwändig vorkommt, alles im Code per Hand zu schreiben, müsstest du ja bei dem QUiLoader auch Abstriche machen. Um dort auf die internen Widgets zuzugreifen, ist es dann nötig sie z.B. mit findChild im QObject-Baum vom (durch den Loader erzeugten) Widget zu suchen.
    Dazu dann das uic Tool (User Interface Compiler), auf das man auch verzichten kann, wenn keine .ui im Spiel ist (Stichwort Codegenerierung).

    Betrifft das gesamte Qt Framework, egal in welcher Form und Sprache man es einsetzt.
    In C++ durch den UICompiler von Qt:

    • wird meinWidget.ui zu ui_meinWidget.h

    Diesen Header kann man dann einbinden. Daraus eine Instanz der UI-Klasse erstellen und ist dann in der Lage die Widgets aus der UI - Datei mit ui->objektname zu adressieren.

    In Python entsprechend:

    • meinWidget.ui zu meinWidget.py

    Alles in "Qt für Python", egal ob PySide oder PyQt wurde von C++ adaptiert, da Qt ein C++ GUI Framework ist. PySide und PyQt sind Bindings, die später dazuentwickelt wurden.
    Darum musste auch ein Tool zum Übersetzen der UI Dateien in etwas "Python-Nutzbares" existieren, auch wenn diese zusätzliche Codegenerierung nicht der Philosophie einer "dynamischen" und Interpreter-Sprache (wie Python) entspricht.

    Da deine UI jetzt nicht besonders komplex ist, wäre es sogar einfacher sie ohne jedliche UI oder den Designer zusammenzusetzen. So würde ich es machen, nach einigen Jahren Erfahrung mit Qt (mag am Anfang aber etwas schwieriger sein)
    Der Designer ist verlockend weil es relativ schnell und einfach ist, aber dann muss man auch mit den Kehrseiten leben :)
    Entweder die Code-Generierung durch UIC oder, beim QUiLoader etwas umständlich auf die Widgets zuzugreifen zu müssen.
    Sonst bleibt nur der Weg "zu Fuß" ;-)

    Im Endeffekt ist alles Geschmackssache bzw. auch etwas abhängig vom Use-Case und Art der App, die man entwickelt (und für wen).

    Zu den Warnungen kann ich leider nichts sagen... Möglicherweise kann man die Qt Syntax der IDE beibringen.
    Hab dazu den Bugreport hier gefunden:

    Schon mal VS Code statt PyCharm versucht?

    Ich würde es dann nach der von dir erwähnten Methode Nr. 1 machen. Da es für mich, aus der Sicht von Python, keinen Sinnvollen Grund gibt es anders zu machen. Und außerdem kenne ich mich auch nicht so gut aus, dass ich selbst entscheiden könnte ob die Warnungen zu ignorieren sind.

    Ja, dies habe ich in dem Post obendrüber ja schon umgesetzt. Kann ich dies so lassen, oder gibt es verbesserung's Vorschläge?

    Denke zum Lernen und Herumexperimentieren mit Qt und QtDesigner ist das die beste und einfachste Lösung.
    So muss man sich keine Gedanken machen, und hat innerhalb der Klasse überall vollen Zugriff auf die UI mittels self.ui.<objekt_name>.
    Alles Weitere kommt dann mit der Zeit :)

    If debugging is the process of removing software bugs, then programming must be the process of putting them in.

    ~E. W. Dijkstra

    M1 ReplyLast reply

  • PPl45m4

    @Master_Shredder said in Wie kann ich Widgets ansprechen(pyside6)?:

    🤦Ich musste gerade feststellen, dass das Programm in der Konstellation mit findChild() beim Button läuft!

    Haha ok, gut zu hören.

    Vielleicht kam es bei dir zu Verwirrung 😅.

    Ja weil ich mir nicht mehr sicher war wie es in Python funktioniert mit der Verbindung. Ob die Klasse, wo eine Funktion mit einem Signal verbunden ist, ein QObject sein muss oder nicht (in C++ kann man nur QObject Klassen direkt verbinden).
    Anscheinend muss es in PySide nicht so sein...

    Funktioniert, sichtlich, wunderbar.

    Ja das ist einer der "empfohlenen Wege", wie man den QtDesigner nutzt. Ob man es so macht, ist ja jedem selbst überlassen.

    @Master_Shredder said in Wie kann ich Widgets ansprechen(pyside6)?:

    "Ich nehme die *.uic-Dateien, weil Quelltext generieren ein unnötiger Zwischenschritt ist, und sich dann auch das Problem nicht stellt generierte Dateien in der Versionsverwaltung zu haben oder nicht.

    Gegen die Warnungen kannst Du nicht wirklich was machen, ausser sie komplett abschalten. Damit muss man bei dynamischen Programmiersprachen halt leben das es Grenzen bei der statischen Analyse von Quelltext gibt."

    Die Verwendung vom Designer macht den Code bzw. Anwendung etwas schwerer zu debuggen und für Dritte zu verstehen.
    Deswegen wird in professionellen QtWidget-Apps meist kein Designer genutzt (QML/QtDesign Studio ist nochmal eine andere Geschichte). Gerade weil man irgendwann sehr limitiert ist, in dem was man tun/umsetzen kann. Daher ist man dann zwangsläufig auf eine (unübersichtliche) Hybrid-Lösung angewiesen.
    Aus dem Grund verzichten viele eher komplett auf den QtDesigner und die .ui Dateien und schreiben ihre GUI selbst. Resultiert dann zwar in mehr Code, ist aber übersichtlicher. Da sieht dann jeder Leser von dem Code direkt was er bekommt (zu erwarten hat) und muss nicht noch irgendwelche XML Blöcke oder automatisch generierte Dateien durchsuchen.

    Auch wenn du sagst, dass es dir aufwändig vorkommt, alles im Code per Hand zu schreiben, müsstest du ja bei dem QUiLoader auch Abstriche machen. Um dort auf die internen Widgets zuzugreifen, ist es dann nötig sie z.B. mit findChild im QObject-Baum vom (durch den Loader erzeugten) Widget zu suchen.
    Dazu dann das uic Tool (User Interface Compiler), auf das man auch verzichten kann, wenn keine .ui im Spiel ist (Stichwort Codegenerierung).

    Betrifft das gesamte Qt Framework, egal in welcher Form und Sprache man es einsetzt.
    In C++ durch den UICompiler von Qt:

    • wird meinWidget.ui zu ui_meinWidget.h

    Diesen Header kann man dann einbinden. Daraus eine Instanz der UI-Klasse erstellen und ist dann in der Lage die Widgets aus der UI - Datei mit ui->objektname zu adressieren.

    In Python entsprechend:

    • meinWidget.ui zu meinWidget.py

    Alles in "Qt für Python", egal ob PySide oder PyQt wurde von C++ adaptiert, da Qt ein C++ GUI Framework ist. PySide und PyQt sind Bindings, die später dazuentwickelt wurden.
    Darum musste auch ein Tool zum Übersetzen der UI Dateien in etwas "Python-Nutzbares" existieren, auch wenn diese zusätzliche Codegenerierung nicht der Philosophie einer "dynamischen" und Interpreter-Sprache (wie Python) entspricht.

    Da deine UI jetzt nicht besonders komplex ist, wäre es sogar einfacher sie ohne jedliche UI oder den Designer zusammenzusetzen. So würde ich es machen, nach einigen Jahren Erfahrung mit Qt (mag am Anfang aber etwas schwieriger sein)
    Der Designer ist verlockend weil es relativ schnell und einfach ist, aber dann muss man auch mit den Kehrseiten leben :)
    Entweder die Code-Generierung durch UIC oder, beim QUiLoader etwas umständlich auf die Widgets zuzugreifen zu müssen.
    Sonst bleibt nur der Weg "zu Fuß" ;-)

    Im Endeffekt ist alles Geschmackssache bzw. auch etwas abhängig vom Use-Case und Art der App, die man entwickelt (und für wen).

    Zu den Warnungen kann ich leider nichts sagen... Möglicherweise kann man die Qt Syntax der IDE beibringen.
    Hab dazu den Bugreport hier gefunden:

    Schon mal VS Code statt PyCharm versucht?

    Ich würde es dann nach der von dir erwähnten Methode Nr. 1 machen. Da es für mich, aus der Sicht von Python, keinen Sinnvollen Grund gibt es anders zu machen. Und außerdem kenne ich mich auch nicht so gut aus, dass ich selbst entscheiden könnte ob die Warnungen zu ignorieren sind.

    Ja, dies habe ich in dem Post obendrüber ja schon umgesetzt. Kann ich dies so lassen, oder gibt es verbesserung's Vorschläge?

    Denke zum Lernen und Herumexperimentieren mit Qt und QtDesigner ist das die beste und einfachste Lösung.
    So muss man sich keine Gedanken machen, und hat innerhalb der Klasse überall vollen Zugriff auf die UI mittels self.ui.<objekt_name>.
    Alles Weitere kommt dann mit der Zeit :)

    MOffline

    MOffline

    Master_Shredder

    wrote on last edited by

    #12

    @Pl45m4 said in Wie kann ich Widgets ansprechen(pyside6)?:

    Ja das ist einer der "empfohlenen Wege", wie man den QtDesigner nutzt. Ob man es so macht, ist ja jedem selbst überlassen.

    Ja so lasse ich es auch jetzt. Das sieht gut aus. Bevor ich mich auf Irrwege mache und am Ende nichts davon verstehe.

    Denke zum Lernen und Herumexperimentieren mit Qt und QtDesigner ist das die beste und einfachste Lösung.
    So muss man sich keine Gedanken machen, und hat innerhalb der Klasse überall vollen Zugriff auf die UI mittels self.ui.<objekt_name>.
    Alles Weitere kommt dann mit der Zeit :)

    Ja denke ich auch. Dies ist wunderbar :).

    OK. Dann dankeschön für die Hilfe.

    1 ReplyLast reply

  • M Master_Shredder has marked this topic as solved on
Wie kann ich Widgets ansprechen(pyside6)? (2025)
Top Articles
Latest Posts
Recommended Articles
Article information

Author: Kerri Lueilwitz

Last Updated:

Views: 6184

Rating: 4.7 / 5 (67 voted)

Reviews: 82% of readers found this page helpful

Author information

Name: Kerri Lueilwitz

Birthday: 1992-10-31

Address: Suite 878 3699 Chantelle Roads, Colebury, NC 68599

Phone: +6111989609516

Job: Chief Farming Manager

Hobby: Mycology, Stone skipping, Dowsing, Whittling, Taxidermy, Sand art, Roller skating

Introduction: My name is Kerri Lueilwitz, I am a courageous, gentle, quaint, thankful, outstanding, brave, vast person who loves writing and wants to share my knowledge and understanding with you.