PyQt5: Einbinden einer *.ui-Datei zur Laufzeit des Programms

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
crazyprogrammer
User
Beiträge: 39
Registriert: Sonntag 27. Juli 2014, 19:06

Hallo,
ich habe mir bereits einige Themen in diesem Forum sowie einige Tutorials angeschaut, bekomme aber mit meinem Programm immer Schwierigkeiten.
Ich will eine *.ui-Datei, die vom Qt Designer erstellt wurde, durch eine *.py-Datei zur Laufzeit dieser einbinden und verwenden. Beide Dateien liegen im gleichen Verzeichnis.
Dazu habe ich ein Beispiel aus dem Buch "Python 3" von Johannes Ernesti und Peter Kaiserauf Seite 835 abgetippt. Erst als ich einen NameError bekam, das er kein Modul/Paket namens PyQt4 kennt, wurde mir mein Fehler klar.
Aber trotzdem mache ich immer irgendwelche Fehler, die ich nicht verstehe. :-(
Kann mir jemand helfen?
Danke im Vorraus
Malta
User
Beiträge: 83
Registriert: Samstag 8. Januar 2011, 23:51

Es wäre hilfreich zu wissen welchen Fehler du hast?
Da wird auch eine Zeilennummer angegeben und wenn du noch den dazugehörenden Code postest wird dir meistens recht schnell die passende Antwort dazu gegeben. Den nicht jeder hat das Buch zuhause.

Code: Alles auswählen

from PyQt5 import QtGui, QtCore, QtWidgets, uic

class LottoSimuDialog(QtWidgets.QMainWindow):
    QtWidgets.QDialog.__init__(self)
    # Set up the user interface from Designer.
    self.ui = uic.loadUi("lottosimu_gui.ui")
crazyprogrammer
User
Beiträge: 39
Registriert: Sonntag 27. Juli 2014, 19:06

Ich habe genau den Code eingegeben, den du gepostet hattest (bis auf den Namen der *.ui-Datei). Dann sah der Code so aus:

Code: Alles auswählen

from PyQt5 import QtGui, QtCore, QtWidgets, uic

class LottoSimuDialog(QtWidgets.QMainWindow):
    QtWidgets.QDialog.__init__(self)
    # Set up the user interface from Designer.
    self.ui = uic.loadUi("register.ui")
Und ich habe beim Ausführen dann diesen Fehler erhalten:

Code: Alles auswählen

Traceback (most recent call last):
  File "C:\...\import-gui.py", line 16, in <module>
    class LottoSimuDialog(QtWidgets.QMainWindow):
  File "C:\...\import-gui.py", line 17, in LottoSimuDialog
    QtWidgets.QDialog.__init__(self)
NameError: name 'self' is not defined
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Du musst das ganze noch in eine __init__-Methode stecken.
Das Leben ist wie ein Tennisball.
crazyprogrammer
User
Beiträge: 39
Registriert: Sonntag 27. Juli 2014, 19:06

Dann stürzt mein PC ab und es kommt nach geraumer Zeit eine Fehlermeldung der IDLE, die ungefähr so lautet:
"IDLE can't make subprocess..."
crazyprogrammer
User
Beiträge: 39
Registriert: Sonntag 27. Juli 2014, 19:06

Dann stürzt mein PC ab und es kommt nach geraumer Zeit eine Fehlermeldung der IDLE, die ungefähr so lautet:
"IDLE can't make subprocess..."
Benutzeravatar
Madmartigan
User
Beiträge: 200
Registriert: Donnerstag 18. Juli 2013, 07:59
Wohnort: Berlin

Dein PC stürzt ab? Dann würde ich ihn an deiner Stelle doch am besten am Boden verankern... :roll:

Spaß beiseite, was genau ist denn die Fehlermeldung? Wie sieht der gesamte Code aus, der den Fehler produziert? Bitte keine Bruchstücke posten.

*.ui Files kannst du bequem zur Laufzeit laden, wie das geht wurde dir bereits anhand direkter Codesamples gezeigt. Oder hast du sie nicht verstanden?

1. Implementiere eine Container-Klasse (QMainWindow, QWidget, QFrame, ... etc.)
2. Lade das UI File via uic im Konstruktor dieser Klasse (__init__())
3. Erstelle eine Instanz dieser Klasse (ggf. sorge dafür, dass sie sichtbar ist. Show()).

Wenn du Schwierigkeiten im Umgang mit IDLE hast, dann verzichte darauf. Python lässt sich auch wunderbar in einem Standard Editor schreiben und per Kommandozeile ausführen. Als Anfänger sind einem die etablierten IDEs oft ein Hindernis. Wenn du darauf nicht verzichten willst, kannst du alternativ Eclipse/PyDev oder PTVS probieren
BlackJack

Also ich weiss ja nicht, bei mir hat IDLE gerade Respekt erlangt. *Nachdem* der *PC* *abgestürzt* ist, kann das noch eine Fehlermeldung absetzen. Ganz schön zäh das Programm, würde ich mal sagen. :twisted:
crazyprogrammer
User
Beiträge: 39
Registriert: Sonntag 27. Juli 2014, 19:06

@BlackJack: Ich hatte noch keinen absturzfreien Tag im Dezember... :roll:
Könnte das an meinem alten PC liegen und nicht unbedingt an mir liegen?

@Madmartigan: Der gesamte Code der Datei "import_register_fast.py" lautet:

Code: Alles auswählen

from PyQt5 import QtGui, QtCore, QtWidgets, uic
     
class RegisterDialog(QtWidgets.QMainWindow):
    def __init__(self):
        QtWidgets.QDialog.__init__(self)
        # Set up the user interface from Designer.
        self.ui = uic.loadUi("register.ui")

gui = RegisterDialog()
gui.show()
Wenn ich dann F5 drücke, dauert es ca. 30 Sekunden, bis die Python 3.4.1 Shell fertig gerechnet hat und ein Ergebnis vorliegt. Dieses ist eine Meldung mit dem Titel "pythonw.exe" und dem Inhalt, dass das Programm "pythonw.exe" abgestürzt sei. Es wäre ein Probelembericht erstellt worden, den man dann versenden könne.
BlackJack

@crazyprogrammer: Wir haben da auf jeden Fall schon mal das Problem das Du die `__init__()` von einer anderen Klasse aufrufst als die von der Deine Klasse erbt.

Und Dein PC stürzt nicht ab. Jedenfalls nicht wenn danach noch Programme etwas tun, denn wenn der PC abstürzt geht *gar nichts mehr* ausser einem Neustart des Rechners. Dir stürzt ”nur” das Python-Programm ab.
crazyprogrammer
User
Beiträge: 39
Registriert: Sonntag 27. Juli 2014, 19:06

@BlackJack: OK, das mit dem PC stimmt schon, es stürzt ja eigentlich nur pythonw.exe ab, aber es passiert mir auch immer wieder, dass er nach zu langer Betriebszeit abstürzt, weil er vielleicht überhitzt. Wenn ich ihn dann eine Stunde abkühlen lasse, kann ich ihn wieder benutzen.

Ich habe jetzt die Klassen geändert. Aber welche Klasse soll ich denn überhaupt verwenden? Wenn ich folgenden Code ausführe, stürzt pythonw.exe ab:

Code: Alles auswählen

from PyQt5 import QtGui, QtCore, QtWidgets, uic
     
class RegisterDialog(QtWidgets.QMainWindow):
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        # Set up the user interface from Designer.
        self.ui = uic.loadUi("register.ui")

gui = RegisterDialog()
gui.show()
Aber wenn ich den Code ausführe, stürzt pythonw.exe auch ab!

Code: Alles auswählen

from PyQt5 import QtGui, QtCore, QtWidgets, uic
     
class RegisterDialog(QtWidgets.QDialog):
    def __init__(self):
        QtWidgets.QDialog.__init__(self)
        # Set up the user interface from Designer.
        self.ui = uic.loadUi("register.ui")

gui = RegisterDialog()
gui.show()
Was mache ich denn falsch?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Starte das Programm doch mal, wie weiter oben schon vorgeschlagen, über die Kommandozeile. Dann bekommst du auch die Fehlermeldung zu Gesicht. Das bietet sich beim Entwickeln generell an.
Das Leben ist wie ein Tennisball.
crazyprogrammer
User
Beiträge: 39
Registriert: Sonntag 27. Juli 2014, 19:06

Das habe ich ja schon gemacht. Ich habe cmd aufgerufen und den Pfad ins Verzeichnis gewechselt, wo die Datei "import_register_fast.py" liegt. Dann habe ich ihren Namen noch ein weiteres Mal eingegeben, um es auszuführen. Das Ergebnis war keineswegs eine Fehlermeldung, sondern wieder dieses Programm-Absturz-Bericht-Fenster, nur das der Name des Programms nicht "pythonw.exe", sondern "python.exe" war.
In der Konsole wurde dann einfach eine Zeile frei gelassen und der Verzeichnispfad angezeigt.
Benutzeravatar
Madmartigan
User
Beiträge: 200
Registriert: Donnerstag 18. Juli 2013, 07:59
Wohnort: Berlin

Das kann so auch nicht funktionieren.
Bevor du ein Fenster erzeugst, brauchst du einen EventLoop/MainLoop. Sonst kannst du kein Widget erzeugen.

Dafür gibt es QApplication bzw. in Qt5 QGuiApplication. Du benötigst eine Instanz davon bevor(!) du irgendwelche UI-Elemente erzeugst.

Final musst du die Application Instanz noch ausführen (exec_()).
crazyprogrammer
User
Beiträge: 39
Registriert: Sonntag 27. Juli 2014, 19:06

Wenn ich diesen vollständigen Programmcode ausführe, kommt dieser Traceback:
Programm:

Code: Alles auswählen

from PyQt5 import QtGui, QtCore, QtWidgets, uic
     
class RegisterDialog(QtWidgets.QDialog):
    def __init__(self):
        QtWidgets.QDialog.__init__(self)
        # Set up the user interface from Designer.
        self.ui = uic.loadUi("register.ui")

app = QtGui.QGuiApplication()
app.exec_()
gui = RegisterDialog()
gui.show()
Traceback:

Code: Alles auswählen

Traceback (most recent call last):
  File "C:\...\import_register_fast.py", line 9, in <module>
    app = QtGui.QGuiApplication()
TypeError: QGuiApplication(list-of-str): not enough arguments
Welche Liste von Strings soll ich da einsetzten?
BlackJack

@crazyprogrammer: Die Kommandozeilenargumente die dem Skript übergeben wurden.
crazyprogrammer
User
Beiträge: 39
Registriert: Sonntag 27. Juli 2014, 19:06

@BlackJack: Aber es gibt doch gar keine Kommandozeilenargumente, die ich übergeben habe?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Doch: `sys.argv`. Selbst wenn du nichts uebergeben hast enthaelt das den Pfad zum ausgefuehrten Skript.
BlackJack

@crazyprogrammer: Auch keine Argumente sind halt Argumente, auch *das* möchte die Qt-Anwendung ganz gerne wissen. Denn man *könnte* ja Argumente übergeben.
crazyprogrammer
User
Beiträge: 39
Registriert: Sonntag 27. Juli 2014, 19:06

Ich habe das Programm jetzt erweitert. Der Code sieht so aus:

Code: Alles auswählen

import sys
from PyQt5 import QtGui, QtCore, QtWidgets, uic
     
class RegisterDialog(QtWidgets.QDialog):
    def __init__(self):
        QtWidgets.QDialog.__init__(self)
        # Set up the user interface from Designer.
        self.ui = uic.loadUi("register.ui")

app = QtGui.QGuiApplication()
app.exec_(sys.argv)
gui = RegisterDialog()
gui.show()
Aber dieser Traceback wird nach ca. 30 Sekunden angezeigt (danach habe ich sofort per Hand 'sys.argv' eingegeben):

Code: Alles auswählen

>>> 
Traceback (most recent call last):
  File "C:\...\import_register_fast.py", line 10, in <module>
    app = QtGui.QGuiApplication()
TypeError: QGuiApplication(list-of-str): not enough arguments
>>> sys.argv
['C:\\...\\import_register_fast.py']
>>> 
Es funktioniert doch eigentlich?
Antworten