PyQt: Layout in Layout produziert Fehler

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
hurz
User
Beiträge: 12
Registriert: Mittwoch 11. März 2009, 23:47

Hallo zusammen!

Folgendes Problem tritt bei mir auf (Python 2.54, passendes PyQT-Paket):

Ich habe dieses Eingabeformular (für eine Filmdatenbank) im Qt-Designer gestaltet:

Bild

Dem Galileo-Openbook zu Python 2.5 folgend habe ich die gespeicherte *.ui-Datei in eine *.py-Datei umgewandelt und nach Vorschrift eingebunden.

Der folgende Fehler erscheint beim Ausführen des Python-Scripts:

Code: Alles auswählen

  File "C:\Daten\programmieren\python25\filme\eingabe.py", line 127, in setupUi
    self.formLayout.addLayout(self.horizontalLayout, 7, 1, 1, 1)
AttributeError: addLayout
Klingt für mich, als könne man Layouts nicht ineinander verschachteln. :shock: :?
Das kann ich mir eigentlich nicht vorstellen...

Jedenfalls habe ich mit dem Qt-Designer dieses Formular erstellt und am resultierenden Python-Code nichts geändert. Da sollte das doch dann eigentlich fehlerfrei laufen...?

Ich hoffe, ihr könnt mir helfen!
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

addLayout gibt es nur bei BoxLayouts -> QHBoxLayout, QVBoxLayout

Dazu kommt: Schmeiss das Buch weg oder vergiss ganz schnell den objektorientierten Teil.

Der Designer ist für Qt geschrieben, PyQt implementiert Qt aber nicht komplett, so hat beispielsweise das QGridLayout keine addLayout Methode. ;)
Ich persönlich kann dem Grid-Layout aber sowieso nicht besonders viel abgewinnen, schau dir mal QFormLayout an, das ist genau für eine Zwecke gemacht und kommt mit Unterlayouts klar.

http://www.riverbankcomputing.co.uk/sta ... asses.html
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Und außerdem generiert man aus UI-Dateien eigentlich keine PY-Dateien mehr, sondern bindet sie direkt im Code ein, ohne Codegenerierung.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
hurz
User
Beiträge: 12
Registriert: Mittwoch 11. März 2009, 23:47

cofi hat geschrieben:Dazu kommt: Schmeiss das Buch weg oder vergiss ganz schnell den objektorientierten Teil.
Ich kenne Objektorientierung aus Java und C++, da hats mir auch erstmal den Kiefer runtergeklappt, als ich das im Galileobuch gelesen habe. Kennst du denn andere gute Quellen, um mir einen vernünftigen Python-Stil anzueignen? Ich hab auch hier im Forum schon bisschen durchgeschaut, irgendwie scheint es nichts zu geben, was wirklich empfohlen werden kann...?
Der Designer ist für Qt geschrieben, PyQt implementiert Qt aber nicht komplett, so hat beispielsweise das QGridLayout keine addLayout Methode. ;)

Ich persönlich kann dem Grid-Layout aber sowieso nicht besonders viel abgewinnen, schau dir mal QFormLayout an, das ist genau für eine Zwecke gemacht und kommt mit Unterlayouts klar.
Vielleicht sollte man das dem Konvertierprogramm mal mitteilen... :)
Ich hatte schon das QFormLayout verwendet, aber auch das hat keine addLayout-Methode, sondern eine setLayout-Methode. (geistreich... ;) )

Ist es dann empfehlenswert, den QtDesigner in die Tonne zu kloppen und brav den Python-Quellcode zusammenzuklauben? Ich möchte ja nicht jedesmal erst alle Layout-Fehler beheben, bevor das Programm funktioniert...

Oder ist vielleicht ein anderes Grafik-Toolkit besser geeignet für mein Programm? Neben dieser Eingabe-Maske soll es natürlich eine Ausgabe der Filmliste geben, die optimalerweise jeweils mit Vorschaubild des Filmposters ausgestattet ist, und die man zügig durchsuchen kann. Bin ich da bei PyQt überhaupt richtig? Das (hier scheinbar eher verschmähte) Galileo-Buch lobt immerhin:
Da Qt einerseits sehr mächtig ist und andererseits eine wirklich konsequente und gut strukturierte objektorientierte API bereitstellt
hurz
User
Beiträge: 12
Registriert: Mittwoch 11. März 2009, 23:47

Leonidas hat geschrieben:Und außerdem generiert man aus UI-Dateien eigentlich keine PY-Dateien mehr, sondern bindet sie direkt im Code ein, ohne Codegenerierung.
Nach deinem Tip hab ich mich in die Dokumentation von PyQt4 gestürzt. Folgender Code bringt mir einen Absturz von pythonw.exe:

Code: Alles auswählen

from PyQt4 import uic
uic.loadUi("eingabe.ui")
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

hurz hat geschrieben:Bin ich da bei PyQt überhaupt richtig?
Also Qt an sich ist schon nicht übel. Aber du scheinst da entweder fehlerhafte UI-Dateien verfüttert zu haben oder einen Fehler im UI-Loader gefunden zu haben :?

Generell ist es aber durchaus empfehlenswert GUIs in GUI-Designer zu bauen, unabhängig ob das nun der Qt Designer für Qt ist, Visual Studio für Windows-Ressourcen-Dateien oder Glade für GTK+.

Oder wie schaut bei dir der "Absturz" aus? Messagebox mit Fehler oder schließt sich das Programm einfach?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
hurz
User
Beiträge: 12
Registriert: Mittwoch 11. März 2009, 23:47

Leonidas hat geschrieben:Oder wie schaut bei dir der "Absturz" aus? Messagebox mit Fehler oder schließt sich das Programm einfach?
Messagebox: Runtime error von Visual C++...

Folgenden Inhalt hat meine Pythondatei:

Code: Alles auswählen

from PyQt4 import uic
uic.loadUi("eingabe.ui")
Ich habe aber die Pythondatei versehentlich eben direkt ausgeführt, also nicht über IDLE, sondern unter Windows mit nem Doppelklick, und siehe da: gleicher Runtime-Fehler, aber dahinter in der Dos-Box lugt hervor:

Code: Alles auswählen

QWidget: Must construct a QApplication before a QPaintDevice
Klingt eher nach einem Anfängerfehler...? :?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Dann solltest du das wohl noch eine QApplication machen, bevor du die GUI lädst (allerdings denke ich, dass ein Interpreter-Crash dennoch ein Bug der Library ist und nicht passieren sollte).
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
hurz
User
Beiträge: 12
Registriert: Mittwoch 11. März 2009, 23:47

Folgendes habe ich mir mal hergedichtet:

Code: Alles auswählen

import sys
from PyQt4 import QtGui
from PyQt4 import uic

app = QtGui.QApplication(sys.argv)
window = QtGui.QDialog()
uic.loadUi("eingabe.ui")
uic.setupUi(window)

window.show()
sys.exit(app.exec_())
Ich erhalte dann eine lange Liste, von der aber wohl wieder nur die letzte Zeile interessant ist:

Code: Alles auswählen

Traceback (most recent call last):
  File "C:\Daten\programmieren\python25\filme\gui2.py", line 7, in <module>
    uic.loadUi("eingabe.ui")
  File "C:\Python25\lib\site-packages\PyQt4\uic\__init__.py", line 106, in loadUi
    return loader.DynamicUILoader().loadUi(uifile, baseinstance)
  File "C:\Python25\lib\site-packages\PyQt4\uic\Loader\loader.py", line 22, in loadUi
    return self.parse(filename)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 667, in parse
    actor(elem)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 526, in createUserInterface
    self.traverseWidgetTree(elem)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 504, in traverseWidgetTree
    handler(self, child)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 163, in createWidget
    self.traverseWidgetTree(elem)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 504, in traverseWidgetTree
    handler(self, child)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 163, in createWidget
    self.traverseWidgetTree(elem)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 504, in traverseWidgetTree
    handler(self, child)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 320, in createLayout
    self.traverseWidgetTree(elem)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 504, in traverseWidgetTree
    handler(self, child)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 328, in handleItem
    self.traverseWidgetTree(elem)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 504, in traverseWidgetTree
    handler(self, child)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 323, in createLayout
    self.stack.peek().addLayout(layout, *elem.attrib["grid-position"])
AttributeError: addLayout
Anscheinend hängt es daran, dass der Übersetzer für alle Layouts die Methode addLayout() verwendet, obwohl selbige beim QGridLayout und QFormLayout setLayout() heißt.

Was soll ich da tun? Von Python 2.5 auf 2.6 wechseln? Oder dann gleich auf Version 3? Vielleicht gibt es den Bug dort nicht...

Oder kann ich sonst etwas falsch machen, was diesen Fehler erzeugen kann?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

hurz mach mal langsam ;) Am besten ist es immer die Dokumentation von PyQt anzuschaun, besser gesagt die Klassenübersicht um zu schaun was geht, was nicht - s.o.

setLayout != addLayout: Mit ersterem legst du ein Layout für ein Widget fest mit letzterem fügst du eins hinzu. Ein großer Unterschied ;)

Zum Formlayout: Das baut auf Zeilen auf schau dir mal die `addRow' Methoden an, da gibts auch welche mit Layout.

Zu deinen Fehlermeldungen: Die gibts, weil es eben kein addLayout gibt, das sagt ja auch der Error. Und nein die Pythonversion zu wechseln hilft nichts, du musst einfach deine .ui datei so umschreiben, dass du kein GridLayout nutzt, bspw Formlayout nutzen ;)

Zum uic Modul ... ich Werd damit nicht so recht warm, da man damit nur Instanzen des Widgets in der .ui erstellen kann und da der Designer in Bezug zu PyQt nicht so recht zu gebrauchen ist, muss man dann auch wieder MonkeyPatchen -> Der Vorteil dynamischer zu sein, fällt dann auch weg. Aber ich hab den Designer erst vor kurzem für mich entdeckt, vllt find ich da noch was passendes :)
hurz
User
Beiträge: 12
Registriert: Mittwoch 11. März 2009, 23:47

cofi hat geschrieben:hurz mach mal langsam ;)
Ich bin in der pythonischen Sturm-und-Drang-Phase und kaum zu bremsen! :D
Am besten ist es immer die Dokumentation von PyQt anzuschaun, besser gesagt die Klassenübersicht um zu schaun was geht, was nicht - s.o.

setLayout != addLayout: Mit ersterem legst du ein Layout für ein Widget fest mit letzterem fügst du eins hinzu. Ein großer Unterschied ;)

Zum Formlayout: Das baut auf Zeilen auf schau dir mal die `addRow' Methoden an, da gibts auch welche mit Layout.
Ich möchte ja gerade vermeiden, dass ich in dem erzeugten Pythoncode noch rumwurschteln muss... Der Designer soll mir eine korrekte ui-Datei erstellen. Warum tut er das nicht?
Zu deinen Fehlermeldungen: Die gibts, weil es eben kein addLayout gibt, das sagt ja auch der Error. Und nein die Pythonversion zu wechseln hilft nichts, du musst einfach deine .ui datei so umschreiben, dass du kein GridLayout nutzt, bspw Formlayout nutzen ;)
Ich benutze ja das FormLayout schon seit Beginn.
da der Designer in Bezug zu PyQt nicht so recht zu gebrauchen ist, muss man dann auch wieder MonkeyPatchen
Was ist denn das? :?

Also mein Problem scheint zu sein, dass mir der Designer keine korrekte ui-Datei erzeugt, die damit auch nicht eingebunden werden kann. (Programmabsturz)
Bleibt mir wohl nur die Lösung, via pyuic umzuwandeln und dann den erzeugten Pythoncode zu korrigieren...
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Also für mich schaut

Code: Alles auswählen

self.formLayout.addLayout(self.horizontalLayout, 7, 1, 1, 1)
nicht nach einem QFormLayout aus.

Nein ich meinte mit meinen ganzen Kommentaren zu Code nicht, dass du in dem generierten Code rumfummeln sollst, sondern, dass du anschauen sollst was geht und dementsprechend deine .ui-Dateien aufbaust. ;)

http://en.wikipedia.org/wiki/Monkey_patch gibt leider keine deutsche Seite dazu ;)

Ich spiel derweil mal mit meinem Designer, ob ich hinbekomm, was du willst ;)
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

UI: http://paste.pocoo.org/show/107579/

Test-Script: http://paste.pocoo.org/show/107580/

Passt wunderbar ;) Ist aber natürlich nur optisch benutzbar ...
hurz
User
Beiträge: 12
Registriert: Mittwoch 11. März 2009, 23:47

Vielen Dank für die Mühe!

Wie erklärst du mir (und der Weltöffentlichkeit) dann das Folgende?

Code: Alles auswählen

Traceback (most recent call last):
  File "C:\Daten\programmieren\python25\filme\test.py", line 6, in <module>
    window = uic.loadUi("test.ui")
  File "C:\Python25\lib\site-packages\PyQt4\uic\__init__.py", line 106, in loadUi
    return loader.DynamicUILoader().loadUi(uifile, baseinstance)
  File "C:\Python25\lib\site-packages\PyQt4\uic\Loader\loader.py", line 22, in loadUi
    return self.parse(filename)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 667, in parse
    actor(elem)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 526, in createUserInterface
    self.traverseWidgetTree(elem)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 504, in traverseWidgetTree
    handler(self, child)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 320, in createLayout
    self.traverseWidgetTree(elem)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 504, in traverseWidgetTree
    handler(self, child)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 328, in handleItem
    self.traverseWidgetTree(elem)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 504, in traverseWidgetTree
    handler(self, child)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 320, in createLayout
    self.traverseWidgetTree(elem)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 504, in traverseWidgetTree
    handler(self, child)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 328, in handleItem
    self.traverseWidgetTree(elem)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 504, in traverseWidgetTree
    handler(self, child)
  File "C:\Python25\lib\site-packages\PyQt4\uic\uiparser.py", line 323, in createLayout
    self.stack.peek().addLayout(layout, *elem.attrib["grid-position"])
AttributeError: addLayout
Ich stelle mal meinen Quellcode rein, vielleicht kannst du den dann mal bei dir testen?

/Edith: da: http://paste.pocoo.org/show/107587/
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Gute Frage. Bei mir tut das jedenfalls :(

Code: Alles auswählen

In [1]: import sys, PyQt4.QtCore
In [2]: sys.version
Out[2]: '2.6.1 (r261:67515, Feb 23 2009, 00:54:49) \n[GCC 4.3.3]'
In [3]: PyQt4.QtCore.QT_VERSION_STR
Out[3]: '4.4.2'
In [4]: PyQt4.QtCore.PYQT_VERSION_STR
Out[4]: '4.4.4'
lunar

cofi hat geschrieben:Der Designer ist für Qt geschrieben, PyQt implementiert Qt aber nicht komplett
Das ist zwar richtig ...
so hat beispielsweise das QGridLayout keine addLayout Methode. ;)
Das aber nicht. QGridLayout hat auch unter PyQt4 eine .addLayout() Methode: http://paste.pocoo.org/show/107607/
Zum uic Modul ... ich Werd damit nicht so recht warm, da man damit nur Instanzen des Widgets in der .ui erstellen kann
Das ist ebenfalls falsch, man kann sehr wohl auch die Typen laden. Doku lesen hilft. Aber was sollte man mit diesen Typen den anderes tun als Exemplare zu erzeugen? Dann kann man doch auch gleich das Exemplar laden, oder?
und da der Designer in Bezug zu PyQt nicht so recht zu gebrauchen ist, muss man dann auch wieder MonkeyPatchen
Diesen Gedankenschritt verstehe ich nicht: Wieso muss man Monkey-Patchen, um den Designer zu nutzen?
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Bei mir hat QDesigner bisher auch fürs prototyping in Python 1A funktioniert. Ich würde nicht im Traum daran denken, eine komplexere GUI noch von Hand zusammen stricken zu wollen. (Sogar im alten Qt3 hat das Definieren von Methoden funktioniert, dann halt mit Pythoncode, aber egal.)

Dein ui-file fördert bei mir folgendes zutage:

- systemweit (Qt 4.4.3, PyQt 4.4.3) -- failure (jaja Suse mal wieder)
- lokal (Qt 4.5.0-rc1, PyQt 4.5-snapshot-20090225) -- läuft
getestet unter Opensuse 11.1 mit Python 2.6

Ursache des Problems würde ich am ehesten in einer fehlerhaften PyQt-Version suchen (wie bei mir), oder in Abhängigkeitendschungel von Qt --> PyQt <-- Python.
Da Du ja Windows benutzt, stellt sich mir die Frage, ob Du die Pakete selbst kompiliert hast, oder aber die fertigen Binärversionen verwendest. Beim letzterem mußt Du sehr genau auf die angegebenen Abhängigkeiten achten.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ich nehm alles bzgl Designer zurück .. nachdem ich mich ein wenig in der PyQt Dokumentation ausgetobt hatte, hab nun schönen dynamischen Code, danke für den Einspruch ;)

Und das Monkey-patchen war zugegeben weit übertrieben ... es war früh am Morgen, anders kann ich mir auch nicht erklären wie ich das addLayout in der Dokumentation übersehen konnte ... wahrscheinlich, weil ich es sehen wollte, da die Fehlermeldung es ja behauptete :oops:
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Hier mal ein diff der generierten Ui-Klassen:

Code: Alles auswählen

5,6c5,6
< # Created: Thu Mar 12 18:02:49 2009
< #      by: PyQt4 UI code generator 4.4.3
---
> # Created: Thu Mar 12 18:15:10 2009
> #      by: PyQt4 UI code generator 4.5-snapshot-20090225
128c128
<         self.formLayout.addLayout(self.horizontalLayout, 7, 1, 1, 1)
---
>         self.formLayout.setLayout(7, QtGui.QFormLayout.FieldRole, self.horizontalLayout)
150c150
<         self.formLayout.addLayout(self.horizontalLayout_2, 8, 1, 1, 1)
---
>         self.formLayout.setLayout(8, QtGui.QFormLayout.FieldRole, self.horizontalLayout_2)
Der Fehler scheint im uic-Loader 4.4.3 zu stecken, da dieser ungültigen Code generiert.
Die Riverbank-Changelogs sagen hierzu:

Code: Alles auswählen

2008/10/20 10:27:13  phil
Fixed a bug in pyuic's handling of QFormLayout when a layout is being set in a
role rather than a widget.
ergo ist das Problem zwar gefixt, womöglich aber immernoch in den älteren Binärpacketen vorhanden. Vllt. hilft Dir eine Neuinstallation des Windowspacketes von Riverbank, falls das eine neue Version ist als Deine jetzige. (Achtung wegen der Abhängigkeiten)
hurz
User
Beiträge: 12
Registriert: Mittwoch 11. März 2009, 23:47

jerch hat geschrieben:Hier mal ein diff der generierten Ui-Klassen:

Code: Alles auswählen

5,6c5,6
< # Created: Thu Mar 12 18:02:49 2009
< #      by: PyQt4 UI code generator 4.4.3
---
> # Created: Thu Mar 12 18:15:10 2009
> #      by: PyQt4 UI code generator 4.5-snapshot-20090225
128c128
<         self.formLayout.addLayout(self.horizontalLayout, 7, 1, 1, 1)
---
>         self.formLayout.setLayout(7, QtGui.QFormLayout.FieldRole, self.horizontalLayout)
150c150
<         self.formLayout.addLayout(self.horizontalLayout_2, 8, 1, 1, 1)
---
>         self.formLayout.setLayout(8, QtGui.QFormLayout.FieldRole, self.horizontalLayout_2)
Genau den Code habe ich in meiner Pythonfile von Hand ändern müssen.

Der Fehler scheint im uic-Loader 4.4.3 zu stecken, da dieser ungültigen Code generiert.
Die Riverbank-Changelogs sagen hierzu:

Code: Alles auswählen

2008/10/20 10:27:13  phil
Fixed a bug in pyuic's handling of QFormLayout when a layout is being set in a
role rather than a widget.
ergo ist das Problem zwar gefixt, womöglich aber immernoch in den älteren Binärpacketen vorhanden. Vllt. hilft Dir eine Neuinstallation des Windowspacketes von Riverbank, falls das eine neue Version ist als Deine jetzige. (Achtung wegen der Abhängigkeiten)
Das klingt einleuchtend. Mal zum Vergleich zu cofi:

Code: Alles auswählen

>>> import sys
>>> import PyQt4.QtCore
>>> sys.version
'2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit (Intel)]'
>>> PyQt4.QtCore.QT_VERSION_STR
'4.4.1'
>>> PyQt4.QtCore.PYQT_VERSION_STR
'4.4.3'
Ich habe das Windows-Binary-Paket (für Python 2.5) runtergeladen, weil es mit dem source code und selbst kompilieren nicht funktioniert hat.

So wie es aussieht, sollte ich das neuere Paket runterladen - und damit auch Python auf 2.6 updaten... Muss ich dabei was Besonderes beachten? Laufen meine 2.5-Programme alle auch auf 2.6?

Und was meinst du mit dem "Abhängigkeitendschungel" von Qt und Python?
Antworten