Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. International
  3. German
  4. Wie kann ich Widgets ansprechen(pyside6)?
QtWS25 Last Chance

Wie kann ich Widgets ansprechen(pyside6)?

Scheduled Pinned Locked Moved Solved German
12 Posts 2 Posters 1.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Master_Shredder
    wrote on 8 Jul 2024, 19:34 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 sys
    from PySide6.QtUiTools import QUiLoader
    from PySide6.QtWidgets import QApplication
    from PySide6.QtCore import QFile, QIODevice
    
    from Abrechnung import Abrechnung
    
    
    class 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

    P 1 Reply Last reply 9 Jul 2024, 00:51
    0
    • P Pl45m4
      13 Jul 2024, 17:37

      @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:

      • https://bugreports.qt.io/browse/PYSIDE-1052

      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 :)

      M Offline
      M Offline
      Master_Shredder
      wrote on 15 Jul 2024, 19:19 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 Reply Last reply
      0
      • M Master_Shredder
        8 Jul 2024, 19:34

        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 sys
        from PySide6.QtUiTools import QUiLoader
        from PySide6.QtWidgets import QApplication
        from PySide6.QtCore import QFile, QIODevice
        
        from Abrechnung import Abrechnung
        
        
        class 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

        P Online
        P Online
        Pl45m4
        wrote on 9 Jul 2024, 00:51 last edited by Pl45m4 7 Sept 2024, 04:25
        #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

        M 1 Reply Last reply 9 Jul 2024, 15:04
        0
        • P Pl45m4
          9 Jul 2024, 00:51

          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 :)

          M Offline
          M Offline
          Master_Shredder
          wrote on 9 Jul 2024, 15:04 last edited by
          #3

          @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 sys
          
          from PySide6 import QtWidgets
          from PySide6.QtUiTools import QUiLoader
          from PySide6.QtWidgets import QApplication
          from PySide6.QtCore import QFile, QIODevice
          
          from Abrechnung import Abrechnung
          
          
          class 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()
          
          
          P 1 Reply Last reply 9 Jul 2024, 22:03
          0
          • M Master_Shredder
            9 Jul 2024, 15:04

            @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 sys
            
            from PySide6 import QtWidgets
            from PySide6.QtUiTools import QUiLoader
            from PySide6.QtWidgets import QApplication
            from PySide6.QtCore import QFile, QIODevice
            
            from Abrechnung import Abrechnung
            
            
            class 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()
            
            
            P Online
            P Online
            Pl45m4
            wrote on 9 Jul 2024, 22:03 last edited by Pl45m4 7 Sept 2024, 22:15
            #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

            M 1 Reply Last reply 10 Jul 2024, 20:47
            0
            • P Pl45m4
              9 Jul 2024, 22:03

              @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.

              M Offline
              M Offline
              Master_Shredder
              wrote on 10 Jul 2024, 20:47 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 sys
              
              from PySide6 import QtWidgets
              from PySide6.QtCore import QFile, QIODevice
              from PySide6.QtUiTools import QUiLoader
              from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QDialog, QLabel, QSpinBox
              
              from Abrechnung import Abrechnung
              
              
              class 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()
              
              
              P 1 Reply Last reply 11 Jul 2024, 12:53
              0
              • M Master_Shredder
                10 Jul 2024, 20:47

                @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 sys
                
                from PySide6 import QtWidgets
                from PySide6.QtCore import QFile, QIODevice
                from PySide6.QtUiTools import QUiLoader
                from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QDialog, QLabel, QSpinBox
                
                from Abrechnung import Abrechnung
                
                
                class 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()
                
                
                P Online
                P Online
                Pl45m4
                wrote on 11 Jul 2024, 12:53 last edited by Pl45m4 7 Nov 2024, 15:35
                #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

                M 1 Reply Last reply 11 Jul 2024, 19:32
                0
                • P Pl45m4
                  11 Jul 2024, 12:53

                  @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.

                  M Offline
                  M Offline
                  Master_Shredder
                  wrote on 11 Jul 2024, 19:32 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 sys
                  
                  from PySide6 import QtWidgets
                  from PySide6.QtCore import QFile, QIODevice
                  from PySide6.QtUiTools import QUiLoader
                  from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QDialog, QLabel, QSpinBox, QWidget
                  
                  from Abrechnung import Abrechnung
                  
                  
                  class 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 ; )

                  P 1 Reply Last reply 11 Jul 2024, 22:46
                  0
                  • M Master_Shredder
                    11 Jul 2024, 19:32

                    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 sys
                    
                    from PySide6 import QtWidgets
                    from PySide6.QtCore import QFile, QIODevice
                    from PySide6.QtUiTools import QUiLoader
                    from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QDialog, QLabel, QSpinBox, QWidget
                    
                    from Abrechnung import Abrechnung
                    
                    
                    class 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 ; )

                    P Online
                    P Online
                    Pl45m4
                    wrote on 11 Jul 2024, 22:46 last edited by Pl45m4 7 Nov 2024, 23:22
                    #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:

                    • https://www.blog.pythonlibrary.org/2018/05/30/loading-ui-files-in-qt-for-python/

                    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 = 42
                    button.clicked.connect( lambda: self.meineButtonFunktion( variable, button ) )
                    # oder
                    button.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 Reply Last reply
                    0
                    • M Offline
                      M Offline
                      Master_Shredder
                      wrote on 12 Jul 2024, 13:32 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 sys
                      
                      from PySide6 import QtWidgets
                      from PySide6.QtCore import QFile, QIODevice
                      from PySide6.QtUiTools import QUiLoader
                      from PySide6.QtWidgets import QApplication
                      
                      from Abrechnung import Abrechnung
                      
                      
                      class 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 sys
                      
                      from PySide6.QtCore import QFile
                      from PySide6.QtWidgets import QApplication, QMainWindow
                      
                      from Abrechnung import Abrechnung
                      from GUI.Verbrauchsrechner_gui import Ui_MainWindow
                      
                      
                      class 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.

                      P 1 Reply Last reply 13 Jul 2024, 17:37
                      0
                      • M Offline
                        M Offline
                        Master_Shredder
                        wrote on 13 Jul 2024, 12:18 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 Reply Last reply
                        0
                        • M Master_Shredder
                          12 Jul 2024, 13:32

                          🤦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 sys
                          
                          from PySide6 import QtWidgets
                          from PySide6.QtCore import QFile, QIODevice
                          from PySide6.QtUiTools import QUiLoader
                          from PySide6.QtWidgets import QApplication
                          
                          from Abrechnung import Abrechnung
                          
                          
                          class 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 sys
                          
                          from PySide6.QtCore import QFile
                          from PySide6.QtWidgets import QApplication, QMainWindow
                          
                          from Abrechnung import Abrechnung
                          from GUI.Verbrauchsrechner_gui import Ui_MainWindow
                          
                          
                          class 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.

                          P Online
                          P Online
                          Pl45m4
                          wrote on 13 Jul 2024, 17:37 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:

                          • https://bugreports.qt.io/browse/PYSIDE-1052

                          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

                          M 1 Reply Last reply 15 Jul 2024, 19:19
                          0
                          • P Pl45m4
                            13 Jul 2024, 17:37

                            @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:

                            • https://bugreports.qt.io/browse/PYSIDE-1052

                            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 :)

                            M Offline
                            M Offline
                            Master_Shredder
                            wrote on 15 Jul 2024, 19:19 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 Reply Last reply
                            0
                            • M Master_Shredder has marked this topic as solved on 16 Jul 2024, 15:48

                            1/12

                            8 Jul 2024, 19:34

                            • Login

                            • Login or register to search.
                            1 out of 12
                            • First post
                              1/12
                              Last post
                            0
                            • Categories
                            • Recent
                            • Tags
                            • Popular
                            • Users
                            • Groups
                            • Search
                            • Get Qt Extensions
                            • Unsolved