l = QGridLayout(self)
self.layout = l
w = QLabel(self)
w.text = "hello"
w.size = 600, 400
l[0,0] = w
print(l[0,0]) #gibt aus: QLabel("hello")
gäbe es eine möglichkeit ein modul zu erstellen, das auf PyQt4 aufsetzt und quasi dessen getter und setter maskiert und mit builtins ersetzt? damit dir(QWidget) auch nicht u.a. setParent oder sowas zurückliefert
Das scheint mir jetzt eher Monkey-Patch-Fleißarbeit zu sein und ich (sich nicht mit Qt und anderen GUI-Rahmenwerken unter Python auskennend) finde komisch, dass das nicht Teil von pyside (oder wie die Qt-Bindings gerade heißen) ist.
Möglicherweise kann man einfach nach "foo" und "setFoo" in allen Klassen suchen und das dann automatisiert ergänzen. Das sollte doch in 10 Zeilen oder so machbar sein. Hier -> http://www.pyside.org/home-binding/api-extractor/ schreiben die allerdings etwas von einem API-Extractor und vielleicht muss man den einfach schlau genug machen.
Theoretisch ist es möglich, ein solches Modul zu entwickeln, da man über QMetaObject an alle Eigenschaften im Sinne von Qt herankommt, und daraus anschließend Eigenschaften im Sinne von Python machen könnte.
Praktisch ist das keine ganz so gute Idee, denn das führt zwangsläufig zu Namenskonflikten. In Qt haben Eigenschaften und Methoden unterschiedliche Namensräume. Eine von QObject abgeleitete Klasse kann also eine Qt-Eigenschaft namens "foo" und eine Methode namens "foo" haben.
In Python dagegen müssen sich Eigenschaften und Methoden einen Namensraum teilen, es kann nur ein einziges "foo" in einer Klasse geben, und das muss sich entscheiden, ob es Eigenschaft sein will oder Methode.
Das wäre nun alles kein Problem, wenn per definitionem eine Beziehung zwischen Getter und Eigenschaftsname bestehen würde. Die aber gibt es nicht, Getter können benannt werden, wie man lustig ist. Mehr noch, Getter können überladen werden.
In Qt kann es also eine Eigenschaft "foo", eine Methode "foo()" und eine Methode "foo(mit_argument)" geben. Würde man nun die Qt-Eigenschaft "foo" in eine Python-Eigenschaft "foo" umsetzen, fiele die zweite "foo"-Methode über Bord.
Aus diesem Grund verzichten sowohl PyQt als auch pyside auf diese Möglichkeit. Da zumindest PyQt4 aber eine "pyqtConfigure"-Methode bietet, mit der man viele Eigenschaften auf einmal setzen kann, und zudem die Konstruktoren der Objekte ebenfalls so überladen sind, dass man direkt Eigenschaften setzen kann, fällt das eigentlich nicht so ins Gewicht. Da gibt es wichtigeres (z.B. überflüssige Typen wie QString und QVariant transient zu machen).
gemäß des kapselungsgeraffels von c++ und so sind doch die properties c++-versteckt, oder? d.h. hat man über python/sip eh keinen zugriff drauf. wenn man z.b. qwidget.width eingibt, ist das eindeutig die funtion width und nicht evtl. eine property.
das heißt, man müsste sip händisch so konfigurieren, dass sip nicht die methode width in den namespace packt, sondern daraus (und aus setWidth) eine property baut. das bedeutet zwar, dass man kein modul auf pyqt draufbauen kann, aber es bedeutet, dass man die devs von pyside / pyqt zu ner alternativen api überreden könnte (oder zur not forken )
@flying sheep: Qt-Eigenschaften sind nicht „versteckt“, sondern über "QObject.property()" und "QObject.setProperty()" erreichbar. Mit „Kapselungsgeraffel“ hat das auch so ziemlich gar nichts zu tun …
Was den Rest angeht, so habe ich das Gefühl, dass Du meinen Beitrag überhaupt nicht gelesen hast. "QWidget.width" ist zwar eine Methode, aber eben nicht eindeutig. Es kann mehrere überladene Versionen dieser Methode geben. Diese überladenen Methoden kann man nicht mehr erreichen, wenn man pauschal jeden Getter in eine entsprechende Eigenschaft verwandelt.
Falls Du ein konstruiertes Beispiel sehen möchtest, so verweise ich auf meinen Beitrag in einem anderen Forum (dort ist die Syntaxhervorhebung schöner).
außerdem kannte ich das schon. trotzdem danke, denn ich hab beim letzten lesen das hier übersehen und das ist mal echt eine erleichterung!
@lunar: du führst die diskussion öfter, oder? ^^
wegen der namensraumproblematik sei angemerkt, dass eine umsetzung in meinem sinne (mit python-properties) den spaß sowieso inkompatibel zum c++-qt4 macht, man also entsprechende methoden umbenennen könnte. soweit ich weiß ist mir eine solche aber auch noch nie untergekommen. könntest du ein beispiel nennen?
PS: im verinkten beitrag ist auch von qtruby die rede: wie löst das denn die namensraum-problematik? soweit ich weiß sind funktionen in ruby auch objekte.
@flying sheep: So einfach ist das auch nicht. Dieses „Umbenennen“ müsste schließlich automatisiert vonstatten gehen, ohne seinerseits neue Konflikte zu erzeugen. Davon abgesehen, müsste sowas wieder extra dokumentiert werden, da die C++-Dokumentation dann ja nicht mehr greift.
Ein Beispiel für Namenskonflikte zwischen Methoden und Eigenschaften kann ich Dir nicht nennen. Ich habe nicht danach gesucht. Die theoretische Möglichkeit reicht aber schon, damit man das berücksichtigen muss.
Möglich wäre das prinzipiell alles schon, nur eben doch mit verhältnismäßig viel Aufwand. Ob es das jetzt wert ist … ich persönlich finde das jetzt nicht so schlimm, aber ich bin möglicherweise auch zu stark von C++ beeinflusst.
Was Ruby angeht, so habe ich keine Ahnung. Ich kenne weder Ruby noch QtRuby.
lunar hat geschrieben:Was Ruby angeht, so habe ich keine Ahnung. Ich kenne weder Ruby noch QtRuby.
Die Doku zu QtRuby sagt, dass fooBar(), foo_bar(), setFooBar(), set_foo_bar() und foo_bar=() funktionieren. Statt CamelCase geht auch under_score. Statt C-style setter-Methode geht auch der Ruby-typische Setter. Da man in Ruby ja Argument-Klammern weglassen kann, hat man damit die typische Property-Notation fooBar und fooBar=.
Offenbar wird das Ruby-Binding genau wie PHP, C# und Perl aus einer Metabeschreibung generiert. Warum es für Python anders ist, habe ich nicht recherchiert. Wirklich zufriedenstellend finde ich das jedoch alles nicht, denn insbesondere wenn immer auf die C++-Dokumentation verwiesen wird, ist das kein UI-Rahmenwerk für die jeweilige Sprache sondern eines, wo man C++ mit etwas anderer Syntax benutzt.
sma hat geschrieben:Die Doku zu QtRuby sagt, dass fooBar(), foo_bar(), setFooBar(), set_foo_bar() und foo_bar=() funktionieren. Statt CamelCase geht auch under_score. Statt C-style setter-Methode geht auch der Ruby-typische Setter. Da man in Ruby ja Argument-Klammern weglassen kann, hat man damit die typische Property-Notation fooBar und fooBar=.
Tja, "fooBar=()" gibt es nun eben nicht in Python. Da sind Eigenschaften und Methoden unterschiedliche Dinge, und können nicht denselben Namen tragen, was die an sich gute Idee des OP in der Implementierung recht kompliziert macht.
Wirklich zufriedenstellend finde ich das jedoch alles nicht, denn insbesondere wenn immer auf die C++-Dokumentation verwiesen wird, ist das kein UI-Rahmenwerk für die jeweilige Sprache sondern eines, wo man C++ mit etwas anderer Syntax benutzt.
Genau das tut man ja auch, ein natives Python-Rahmenwerk gibt es ja nicht. Es wäre auch schwer, ein in Größe und Qualität ebenbürtiges Rahmenwerk zu implementieren … es wäre auch ziemlich viel Aufwand, nur weil die Namensgebung und die Semantik von Qt-Eigenschaften nicht pythonisch sind
uncool. man müsste halt recherchieren, ob es in qt4 getter mit optionalen argumenten gibt, was ich stark bezweifle und dann für jede funktion "qklasse.prop" , für die es eine setProp-funktion gibt eine python-property anfertigen.
@flying sheep: Du meinst hinsichtlich der Verwendung eines Tupels als Ersatz für QSize und des Zugriffs auf "QGridLayout"?
Nun, ich würde sagen, auch wieder nicht weit genug gedacht. QSize verhält sich anders als ein Tupel (vgl. "QSize(100, 200) * 10" und "(100, 200) * 10"). QGridLayout.addWidget hat neben Zeile und Spalte noch ein Argument für die Ausrichtung, dass bei Deinem Ansatz über "__getitem__()" verloren geht. Man müsste eher "label.size = (100, 200, Qt.AlignCenter)" oder ähnlich verwenden.
aber ein einfacher. wenn man nur zwei argumente verwendet, funktioniert es auch (und ich benutze meist nur die beiden) ansonsten halt mehr tupelelemente, wie du vorgeschlagen hast
qsize sollte auch __getitem__ unterstützen, um auf x und y zuzugreifen. multiassignment, unpacking und so.
ich muss das mal nochmal aufwärmen:
qyoto (qt-bindings für .net) wird automatisch erstellt. dort ist es möglich, properties rubymäßig per qwidget.property=5 zu setzen. d.h. muss es eine methode geben, properties eindeutig zu bestimmen. nun müsste man nur noch das tun, die getter umbenennen und mit einer python-property verknüpfen, fertig ist die laube.