Werteübergabe SIGNAL/SLOT
@Cascoin: Das könnte tatsächlich an der PyQt-Version liegen. Die Version(en) in den GUI-Anwendungen die Du zum Programmieren verwendest sind nicht so interessant wie die, gegen welche die Python-Anbindung gelinkt ist. Das können ja alles drei theoretisch völlig unterschiedliche Versionen sein. Welche Version PyQt4 verwendet, verrät `PyQt4.QtCore.QT_VERSION_STR`.
Die Fehlermeldung sagt ja, dass es keinen passenden C++-Typ für `Student` gibt. Der Abschnitt Old-Style Signal and Slot Support deutet darauf hin was man bei Python-Objekten für einen Typ in der Signatur angeben muss, beziehungsweise das *Short-circuit Signals* eine noch einfachere Lösung sind.
Warum das bei mir auch mit einem Python-Typ in der Signatur funktioniert — keine Ahnung. Aber korrekt laut Dokumentation war mein Beispiel wohl nicht.
Die Fehlermeldung sagt ja, dass es keinen passenden C++-Typ für `Student` gibt. Der Abschnitt Old-Style Signal and Slot Support deutet darauf hin was man bei Python-Objekten für einen Typ in der Signatur angeben muss, beziehungsweise das *Short-circuit Signals* eine noch einfachere Lösung sind.
Warum das bei mir auch mit einem Python-Typ in der Signatur funktioniert — keine Ahnung. Aber korrekt laut Dokumentation war mein Beispiel wohl nicht.
Ok, also wenn ich PyQt4.QtCore.QT_VERSION_STR eingebe wird mir 4.7.1 ausgegeben.... Das ist dann wohl die Qt-Version die Python linked...Mit dem Qt Designer arbeiten wir übrigens gar nicht, er ist zwar installiert aber wir erzeugen alles per Code.....
Den Abschnitt aus der Dokumentation den du angegeben hast kenne ich....Hab schon versucht da das zu verstehen was für mein Problem hilf... Leider hats nicht geklappt....
Welche Version benutzt du eigenltich? Das es ein Versionsfehler ist haben wir auch schon vermutet weil das Programm das ich korrigere ja funktioniert hat bis es zum Versionsupdate kam....
Ich muss einfach weiterprobieren, vielleicht hilfts....
Cascoin
Den Abschnitt aus der Dokumentation den du angegeben hast kenne ich....Hab schon versucht da das zu verstehen was für mein Problem hilf... Leider hats nicht geklappt....
Welche Version benutzt du eigenltich? Das es ein Versionsfehler ist haben wir auch schon vermutet weil das Programm das ich korrigere ja funktioniert hat bis es zum Versionsupdate kam....
Ich muss einfach weiterprobieren, vielleicht hilfts....
Cascoin
@Cascoin: Ich habe hier 4.6.2 installiert:
Laut Dokumentation sind das in den Klammern bei der Signatur C++-Typen. Also C++-Grunddatentypen oder Klassen die in C++ geschrieben sind. Das heisst mein Beispiel ist falsch! Auch wenn das zufällig funktioniert, ist das nichts was man nachmachen und hoffen sollte, dass es schon funktionieren wird. Wenn ihr das also bisher so gemacht habt, dann habt ihr das bisher schlicht falsch gemacht.
`Student` ist ein Python-Datentyp. Und in der Dokumentation steht ziemlich deutlich als was der in Signaturen deklariert werden muss, damit der Wert durch den C++-Code von Qt unverändert durchgereicht wird.
Code: Alles auswählen
In [204]: PyQt4.QtCore.QT_VERSION_STR
Out[204]: '4.6.2'
`Student` ist ein Python-Datentyp. Und in der Dokumentation steht ziemlich deutlich als was der in Signaturen deklariert werden muss, damit der Wert durch den C++-Code von Qt unverändert durchgereicht wird.
@Cascoin: Diese Probleme ließen sich im Übrigen alle vermeiden, wenn Ihr die neue API für Signale und Slots nutzen würdet.
Hallo,
@lunar :
Ich weiß ehrlich gesagt nicht was eine API ist.... Meinst du damit die neue Syntax? Wie dem auch sei, ich möchte an demProgramm nicht allzuviel ändern sondern es einfach nur zum laufen bringen....
@Blackjack:
Ok, jetzt bin ich schon ziemlich nahe an dem Fehler den ich suche..... Du sagtest das in der Doku ziemlich deutlich steht wie mann ein Nicht-C++ Signal durchreichen muss... Naja, ich hab mir die Dokumentation ziemlich oft angeguckt("New-Signal and Slot" Zeugs aus dem Reference Guide) und versucht von den Beispielen auf mein Problem zu schließen....
Also hier mal als erstes die Klasse die ich per Signal senden möchte.
Hier die Klasse mit dem Signal and Slot....
und hier die main()-Klasse in der dann Instanzen von Student & Foo erzeugt werden....
Naja, ich muss ehrlich sagen das ich selbst nicht daran geglaub habe das es klappt weil ich in der Doku auch nicht so 100%ig das passende für mein Problem gefunden habe....
Die Fehlermeldung ist übrigens:-------------------------------------------------------------
Traceback (most recent call last):
File "F:\7. Versuche\test2.py", line 44, in <module>
main()
File "F:\7. Versuche\test2.py", line 40, in main
Test.Sende(Student('Andi', 'MB',12345))
TypeError: unbound method Sende() must be called with Foo instance as first argument (got Student instance instead)
-------------------------------------------------------------------------------------------
Wäre cool wenn mir da jemand weiter wüßte..... Bzw. Vorschläge hätte was ich ändern müßte.....
mfg Cascoin
@lunar :
Ich weiß ehrlich gesagt nicht was eine API ist.... Meinst du damit die neue Syntax? Wie dem auch sei, ich möchte an demProgramm nicht allzuviel ändern sondern es einfach nur zum laufen bringen....
@Blackjack:
Ok, jetzt bin ich schon ziemlich nahe an dem Fehler den ich suche..... Du sagtest das in der Doku ziemlich deutlich steht wie mann ein Nicht-C++ Signal durchreichen muss... Naja, ich hab mir die Dokumentation ziemlich oft angeguckt("New-Signal and Slot" Zeugs aus dem Reference Guide) und versucht von den Beispielen auf mein Problem zu schließen....
Also hier mal als erstes die Klasse die ich per Signal senden möchte.
Code: Alles auswählen
# Meine Klasse die ich senden möchte
class Student(QObject): # Testklasse
def __init__(self, name, Studium, Nr):
QObject.__init__(self)
self.name = name
self.Fach = Studium
self.Matrikel = Nr
Hier die Klasse mit dem Signal and Slot....
Code: Alles auswählen
class Foo(QObject):
# Definiert die Art meines Signals
Sig = pyqtSignal([Student])
#Verbindung von meinem Signal zur Ausgabe/Slot
def Connection_SAS(self):
Sig.connect(Ausgabe([Student]))
#Sendet Signal
def Sende(Student):
self.Sig.emit([Student])
#Ausgabe
def Ausgabe(Student):
print Student.name
und hier die main()-Klasse in der dann Instanzen von Student & Foo erzeugt werden....
Code: Alles auswählen
def main(): # Main
Andi = Student("Andi", "MB", 23523)
Test = Foo
Test.Sende(Student('Andi', 'MB',12345))
if __name__ == '__main__':
main()
Die Fehlermeldung ist übrigens:-------------------------------------------------------------
Traceback (most recent call last):
File "F:\7. Versuche\test2.py", line 44, in <module>
main()
File "F:\7. Versuche\test2.py", line 40, in main
Test.Sende(Student('Andi', 'MB',12345))
TypeError: unbound method Sende() must be called with Foo instance as first argument (got Student instance instead)
-------------------------------------------------------------------------------------------
Wäre cool wenn mir da jemand weiter wüßte..... Bzw. Vorschläge hätte was ich ändern müßte.....
mfg Cascoin
@Cascoin: API = Application Programming Interface = Programmierschnittstelle. Es gibt da keine neue Syntax — die Syntax von Python wird nicht von Modulen von Drittanbietern verändert. Es ist die neue Programmierschnittstelle zum Verbinden gemeint. Die *einfachere*, *”pythonischere”*, *sicherere*. Es ist mir auch ein Rätsel warum Du Dich so vehement dagegen wehrst die zu verwenden. Sie ist da. Sie wird auch nicht weggehen. Sie wird empfohlen! In der Dokumentation steht für die alte API explizit, dass sie noch für die gesamte PyQt 4.er Serie unterstützt wird. Da lese ich aber auch heraus, dass sie danach abgeschafft wird. Warum also nicht jetzt schon das Programm vereinfachen statt in Zukunft durch einen Versionswechsel dann sowieso dazu gezwungen zu werden!? Du willst es einfach nur zum laufen bringen? Damit sollte man es *einfach* zum laufen bringen können!
Dein Versuch zeigt ganz massive Verständnisprobleme bei Python-Grundlagen, die noch nicht einmal etwas mit PyQt oder GUIs zu tun haben. Du kennst die Python-Syntax und Semantik nicht. Das solltest Du erst einmal ganz unabhängig von Deinem konkreten Problem in den Griff bekommen. Wild herumprobieren mit etwas, dessen Semantik man nicht versteht, aber von dem man hofft es könnte das bedeuten was haben möchte, ist nicht zielführend. Du kannst nicht ein PyQt-Programm bearbeiten ohne vorher objektorientierte Programmierung in Python verstanden zu haben.
Dein Versuch zeigt ganz massive Verständnisprobleme bei Python-Grundlagen, die noch nicht einmal etwas mit PyQt oder GUIs zu tun haben. Du kennst die Python-Syntax und Semantik nicht. Das solltest Du erst einmal ganz unabhängig von Deinem konkreten Problem in den Griff bekommen. Wild herumprobieren mit etwas, dessen Semantik man nicht versteht, aber von dem man hofft es könnte das bedeuten was haben möchte, ist nicht zielführend. Du kannst nicht ein PyQt-Programm bearbeiten ohne vorher objektorientierte Programmierung in Python verstanden zu haben.
Hallo,
ja Ok, das ist ein Argument... Dann wirds die neue "gute" Syntax. Sollte ja länger laufen das Programm.
Ich weiß schon selber das ich mich mit Python nicht auskenne... Qt noch ein bisschen mehr aber da ist halt einfach wenig Wissen da... Bisher hats halt gereicht deswegen dachte ich ich würd das schon hinkriegen... Ist nun mal so das sich halt hier am Lehrstuhl scheinbar niemand mit Qt auskennt. Deswegen solls ich ja hinkriegen... Und der wo das Programm geschrieben hat ist jetzt weg... Wie auch immer, ich kann jetzt nicht komplett PyQt lernen...Da ist einfach die Zeit nicht da...
Wenn du schreibst das es einfach aus der Doku zu lesen ist dann muss ich sagen fällt mir das nicht so leicht...
Ich les mir immer diesen Abschnitt hier durch: "http://www.riverbankcomputing.co.uk/sta ... slots.html".
Aber so richtig auf mein Problem bezogen finde ich da nichts.... Das wäre ja auch der "New Style"...
Jetzt zu meinem Versuch:
1: Meine Klasse Foo ist ja vom Typ Object. Damit ist sie ja Signal/Slot sende/empfangen fähig...
2: Jetzt definiere ich mir ein Signal (hier: Sig) das den Datentyp Student versendet.
3: Dann connecte ich mein Signal mit meinem Slot der dieses Signal dann empfängt und ausgeben soll.
So hab ich das aus der Docu herausgelesen. Schon als ich das geschrieben hab ist mir allerdings aufgefallen das ich den Connect selbst eher in den Konstruktor geschrieben hätte... Aber so war des in der Doku auch nicht... Und an die habe ich mich versucht zu halten....
Könnte mir da jemand vielleicht nochmal mit der Syntax helfen? Oder zumindest zeigen wie ich ein Signal erzeuge das einen selber erzeugten Datentyp sendet? Dann hätte ich einen Anfangspunkt....
danke soweit....
Cascoin
ja Ok, das ist ein Argument... Dann wirds die neue "gute" Syntax. Sollte ja länger laufen das Programm.
Ich weiß schon selber das ich mich mit Python nicht auskenne... Qt noch ein bisschen mehr aber da ist halt einfach wenig Wissen da... Bisher hats halt gereicht deswegen dachte ich ich würd das schon hinkriegen... Ist nun mal so das sich halt hier am Lehrstuhl scheinbar niemand mit Qt auskennt. Deswegen solls ich ja hinkriegen... Und der wo das Programm geschrieben hat ist jetzt weg... Wie auch immer, ich kann jetzt nicht komplett PyQt lernen...Da ist einfach die Zeit nicht da...
Wenn du schreibst das es einfach aus der Doku zu lesen ist dann muss ich sagen fällt mir das nicht so leicht...
Ich les mir immer diesen Abschnitt hier durch: "http://www.riverbankcomputing.co.uk/sta ... slots.html".
Aber so richtig auf mein Problem bezogen finde ich da nichts.... Das wäre ja auch der "New Style"...
Jetzt zu meinem Versuch:
1: Meine Klasse Foo ist ja vom Typ Object. Damit ist sie ja Signal/Slot sende/empfangen fähig...
2: Jetzt definiere ich mir ein Signal (hier: Sig) das den Datentyp Student versendet.
3: Dann connecte ich mein Signal mit meinem Slot der dieses Signal dann empfängt und ausgeben soll.
So hab ich das aus der Docu herausgelesen. Schon als ich das geschrieben hab ist mir allerdings aufgefallen das ich den Connect selbst eher in den Konstruktor geschrieben hätte... Aber so war des in der Doku auch nicht... Und an die habe ich mich versucht zu halten....
Könnte mir da jemand vielleicht nochmal mit der Syntax helfen? Oder zumindest zeigen wie ich ein Signal erzeuge das einen selber erzeugten Datentyp sendet? Dann hätte ich einen Anfangspunkt....
danke soweit....
Cascoin
@Cascoin: Das Signal erzeugst Du so schon richtig. Die Fehler die Du machst haben auch mit PyQt nichts zu tun, sondern beruhen offenbar alle auf dem Unverständnis von Python-Grundlagen. Darüber wirst Du also in der PyQt-Dokumentation nichts finden, sondern eher in der Python-Dokumentation und in Python-Tutorials.
Du verbindest das Signal nicht. Davon abgesehen, dass die `Connection_SAS()`-Methode nicht aufgerufen wird, kann der Code darin so nicht funktionieren. Zu den Python-Grundlagen gehört hier zu wissen, dass keinem der Namen innerhalb der Methode etwas zugewiesen wird, und die damit im Modulnamensraum gesucht werden. Weder `Sig` noch `Ausgabe` gibt es aber im Modulnamensraum. Du willst auf Attribute des Exemplars zugreifen, auf dem die Methode aufgerufen wird. Das Exemplar wird bei Methoden immer ”automagisch” als erstes Argument übergeben.
Wenn man das korrigiert, ist der Code aber immer noch semantisch falsch. Erkläre doch mal was da in welcher Reihenfolge ausgeführt wird. Also welcher Teilausdruck wird zu was ausgewertet und welcher Wert wird dann dafür ersetzt.
Der Fehler in den Du mit der gezeigten Ausnahme läufst, ist auch Python-Grundlage. Ungebundene Methoden, also solche auf *Klassen* anstelle von *Exemplaren* erwarten ein Exemplar der Klasse als erstes Argument. Das sollte Dich stutzig machen warum `Sende()` hier als ungebundene Methode angesehen wird. Das liegt daran, dass Du kein Exemplar erstellst, sondern mit ``Test = Foo`` einfach nur die Klasse `Foo` zusätzlich an den Namen `Test` bindest. Exemplare erstellt man, in dem man die Klasse aufruft. Mit dem Aufrufoperator — also Klammern.
Du verbindest das Signal nicht. Davon abgesehen, dass die `Connection_SAS()`-Methode nicht aufgerufen wird, kann der Code darin so nicht funktionieren. Zu den Python-Grundlagen gehört hier zu wissen, dass keinem der Namen innerhalb der Methode etwas zugewiesen wird, und die damit im Modulnamensraum gesucht werden. Weder `Sig` noch `Ausgabe` gibt es aber im Modulnamensraum. Du willst auf Attribute des Exemplars zugreifen, auf dem die Methode aufgerufen wird. Das Exemplar wird bei Methoden immer ”automagisch” als erstes Argument übergeben.
Wenn man das korrigiert, ist der Code aber immer noch semantisch falsch. Erkläre doch mal was da in welcher Reihenfolge ausgeführt wird. Also welcher Teilausdruck wird zu was ausgewertet und welcher Wert wird dann dafür ersetzt.
Der Fehler in den Du mit der gezeigten Ausnahme läufst, ist auch Python-Grundlage. Ungebundene Methoden, also solche auf *Klassen* anstelle von *Exemplaren* erwarten ein Exemplar der Klasse als erstes Argument. Das sollte Dich stutzig machen warum `Sende()` hier als ungebundene Methode angesehen wird. Das liegt daran, dass Du kein Exemplar erstellst, sondern mit ``Test = Foo`` einfach nur die Klasse `Foo` zusätzlich an den Namen `Test` bindest. Exemplare erstellt man, in dem man die Klasse aufruft. Mit dem Aufrufoperator — also Klammern.
Hallo,
danke für die schnelle Antwort. Hab mir deine Vorschläge sehr oft durchgelesen.
Ok, das die Methode Connection_SAS() nicht aufgerufen wird ist ein blöder Fehler, das ist jetzt korregiert.
Jetzt zum 2ten Teil deiner Kritik. Der war vom Verständniss für mich total schwer, aber ich hoffe ich habe es verstanden.
-In einem Modul darf keinem Name eine Methode zugewiesen werden. Ich nehme mal an du meinst mit Name ein Attribut(Wollte ich nur zum besseren Verständniss festhalten). Desweiteren steht geschrieben das weder Sig noch Ausgabe Attribute meiner Klasse seien.
Du machst mich damit also auf Fehler in dem connect_SAS() Befehl aufmerksam.
Jedoch habe ich mir das von der Doku: http://www.riverbankcomputing.co.uk/sta ... slots.html abgeschaut. Da gibt es unter der Überschrift "Connecting, Disconnecting and Emitting Signals" ein Beispiel mit einer Klasse Foo. Da wird auch ein Signal erzeugt (Das Signal heißt Trigger) und der connect Befehl dann so geschrieben:
self.trigger.connect(self.handle_trigger) ...Ja und dann hab ichs analog gemacht.
self.Sig.connect(Ausgabe)
Was ich jetzt glaube ich verstanden hab ist, das man eine Methode an ein Exemplar binden muß. Das geschieht indem ich in der Klasse das self in die Klammer schreibe... War mir so ehrlich gesagt nicht klar...
Jetzt noch etwas zu den Signalen. Ich erzeuge mein Signal richtig wie hast du gesagt. Der Sende()-Funktion muss ja aber der Datentyp Student übergeben werden. Schreibe ich da jetzt def Sende(self, Student): oder def Sende(self,Sig):? Bei der Ausgabe hab ich ja auch das gleiche Problem. Da weiß ich einfach net was ich da schreiben soll....
Und warum wird mein Signal nicht erkannt? Gab schon oft die Fehlermeldung "global name Sig is not definiert"..... Find ich auch komisch... Hab ich ja oben hingeschrieben.....
Noch auf deine letzte Frage bezüglich der Reihenfolge der Zuweisungen: (Ich beziehe mich allerdings auf meinen bis jetzt korrigierten Code (s.unten) )
1. Ich fange mit der main()-Funktion an.
1.1 Erzeugung ein Student Exemplares das ich Andi nenne.
1.2 Diesem Exemplar Andi weiße ich seine Attribute zu. Nämlich den Attributname self.name -> "Andi" usw.
1.3 Jetzt erzeuge ich deine Exemplar von der Foo Klasse. Dieses Exemplar nenne ich Test.
2 Generelle Ablauf wenn ein Exemplar von Foo erzeugt wird.
2.1 Der Konstruktor wird aufgerufen. In diesem Moment wird die Methode connect_SAS aufgerufen die sofort das Signal Sig mit der Ausgabe verbindet. D.h. immer wenn ein Sig-Signal emmitiert wird, tut die Ausgabe Methode dieses Signal empfangen.
2.2 Dann steht da geschrieben wie ich mir ein Signal definiere. Also gibt es einen Signaltyp den ich Sig nenne, der den Datentyp Signal sendet.
2.3 In der Methode Sende() wird dann dieses Signal ausdrücklich emmitiert. Dieser Methode muss ich allerdings noch ein Exemplar des Datentyps Student übergeben damit eindeutig ist welches Signal versendet werden soll.
3 Wenn dann in der main()-Funktion z.b. Test.Sende(Andi) geschrieben steht, dann wird der Methode Sende() des Exemplars Test der Datentyp Andi übergeben der dann gesendet empfangen und letztendlich von Ausgabe geprinted wird.....
So SOLL es zumindest werden.... Funzt aber nicht..... Hier erstmal der Code...
Hier die Fehlermeldung:
Diese Fehlermeldung ärgert mich jetzt ganz besonders da ich dachte ich hätte die Methoden an Exemplare gebunden. Warum das nicht so ist, keine Ahnung.
Jo, für Hilfen wäre/bin ich sehr dankbar. Das Forum ist echt super.
mfg
danke für die schnelle Antwort. Hab mir deine Vorschläge sehr oft durchgelesen.
Ok, das die Methode Connection_SAS() nicht aufgerufen wird ist ein blöder Fehler, das ist jetzt korregiert.
Jetzt zum 2ten Teil deiner Kritik. Der war vom Verständniss für mich total schwer, aber ich hoffe ich habe es verstanden.
-In einem Modul darf keinem Name eine Methode zugewiesen werden. Ich nehme mal an du meinst mit Name ein Attribut(Wollte ich nur zum besseren Verständniss festhalten). Desweiteren steht geschrieben das weder Sig noch Ausgabe Attribute meiner Klasse seien.
Du machst mich damit also auf Fehler in dem connect_SAS() Befehl aufmerksam.
Jedoch habe ich mir das von der Doku: http://www.riverbankcomputing.co.uk/sta ... slots.html abgeschaut. Da gibt es unter der Überschrift "Connecting, Disconnecting and Emitting Signals" ein Beispiel mit einer Klasse Foo. Da wird auch ein Signal erzeugt (Das Signal heißt Trigger) und der connect Befehl dann so geschrieben:
self.trigger.connect(self.handle_trigger) ...Ja und dann hab ichs analog gemacht.
self.Sig.connect(Ausgabe)
Was ich jetzt glaube ich verstanden hab ist, das man eine Methode an ein Exemplar binden muß. Das geschieht indem ich in der Klasse
Code: Alles auswählen
def Funktion(self):
Jetzt noch etwas zu den Signalen. Ich erzeuge mein Signal richtig wie hast du gesagt. Der Sende()-Funktion muss ja aber der Datentyp Student übergeben werden. Schreibe ich da jetzt def Sende(self, Student): oder def Sende(self,Sig):? Bei der Ausgabe hab ich ja auch das gleiche Problem. Da weiß ich einfach net was ich da schreiben soll....
Und warum wird mein Signal nicht erkannt? Gab schon oft die Fehlermeldung "global name Sig is not definiert"..... Find ich auch komisch... Hab ich ja oben hingeschrieben.....
Noch auf deine letzte Frage bezüglich der Reihenfolge der Zuweisungen: (Ich beziehe mich allerdings auf meinen bis jetzt korrigierten Code (s.unten) )
1. Ich fange mit der main()-Funktion an.
1.1 Erzeugung ein Student Exemplares das ich Andi nenne.
1.2 Diesem Exemplar Andi weiße ich seine Attribute zu. Nämlich den Attributname self.name -> "Andi" usw.
1.3 Jetzt erzeuge ich deine Exemplar von der Foo Klasse. Dieses Exemplar nenne ich Test.
2 Generelle Ablauf wenn ein Exemplar von Foo erzeugt wird.
2.1 Der Konstruktor wird aufgerufen. In diesem Moment wird die Methode connect_SAS aufgerufen die sofort das Signal Sig mit der Ausgabe verbindet. D.h. immer wenn ein Sig-Signal emmitiert wird, tut die Ausgabe Methode dieses Signal empfangen.
2.2 Dann steht da geschrieben wie ich mir ein Signal definiere. Also gibt es einen Signaltyp den ich Sig nenne, der den Datentyp Signal sendet.
2.3 In der Methode Sende() wird dann dieses Signal ausdrücklich emmitiert. Dieser Methode muss ich allerdings noch ein Exemplar des Datentyps Student übergeben damit eindeutig ist welches Signal versendet werden soll.
3 Wenn dann in der main()-Funktion z.b. Test.Sende(Andi) geschrieben steht, dann wird der Methode Sende() des Exemplars Test der Datentyp Andi übergeben der dann gesendet empfangen und letztendlich von Ausgabe geprinted wird.....
So SOLL es zumindest werden.... Funzt aber nicht..... Hier erstmal der Code...
Code: Alles auswählen
class Foo(QObject):
def __init__(self, parent=None): # Konstruktor
self.Connection_SAS() # Verbindet Signal&Slot
# Definiert die Art meines Signals
Sig = pyqtSignal([Student])
#Verbindung von meinem Signal zur Ausgabe/Slot
def Connection_SAS(self):
self.Sig.connect(self.Ausgabe)
#Sendet Signal
def Sende(self, Student):
self.emit([Sig])
#Ausgabe
def Ausgabe(self):
print Student.name
def main(): # Main
Andi = Student("Andi", "MB", 23523)
Test = Foo()
Test.Sende(Andi)
Code: Alles auswählen
File "F:\9. Versuche\test.py", line 30, in Connection_SAS
self.Sig.connect(self.Ausgabe)
TypeError: pyqtSignal must be bound to a QObject, not 'Foo'
Jo, für Hilfen wäre/bin ich sehr dankbar. Das Forum ist echt super.
mfg
Zuletzt geändert von Cascoin am Freitag 17. Juni 2011, 14:42, insgesamt 2-mal geändert.
Du musst den Konstruktor der Vaterklasse aufrufen:
Unterlässt Du diesen Aufruf, ist das Objekt für Qt in einem undefinierten Zustand, folglich kann man auch keine Qt-Signale verbinden.
Code: Alles auswählen
class Foo(QObject):
def __init__(self, parent=None):
QObject.__init__(self, parent)
@Cascoin: Mit Name meinte ich Name. Und ich verstehe nicht so ganz was Du darüber im zweiten Absatz schreibst. Natürlich kann man Namen auf Modulebene auch Methoden als Werte zuweisen. Du versuchst in der alten `Connection_SAS()` aber auf `Sig` auf Modulebene zuzugreifen, dass es dort einfach nicht gibt. Genausowenig wie `Ausgabe`. Beides sind aber sehr wohl Attribute auf Deiner Klasse und damit auch auf Exemplaren davon. Das muss man beim Zugriff aber auch sagen, denn sonst wird halt im Modulnamensraum gesucht, wo es die Namen nicht gibt. Du hast eben nicht wie im Beispiel aus der Dokumentation über `self.Sig` auf das Signal-Objekt zugegriffen, sondern nur `Sig` geschrieben. Das führt zu „global name Sig is not defined”.
Eine Methode wird automatisch an ein Exemplar gebunden — da muss man nicht extra etwas für tun. Und wenn man sie auf einem Exemplar aufruft, wird dieses Exemplar auch automatisch als erstes Argument übergeben. Also braucht man in der Argumentliste auch einen formalen Parameter an den es dann gebunden werden kann. Per Konvention heisst der `self`.
Um mal ein bisschen pedantisch zu sein: Der Sendefunktion muss nicht der Datentyp `Student` übergeben werden, sondern ein Objekt vom Typ `Student`. `Student`, also der Datentyp ist ja selbst auch ein Objekt, aber das will man dort nicht als Wert übergeben, sondern einen konkreten Studenten.
Die Funktionssignatur kann ``def Sende(self, Student)``, ``def Sende(self, Sig)``, oder auch ``def Sende(self, Telefonbuch)`` sein. Das hat keine semantischen Auswirkungen. Man sollte einen Namen wählen, der die Bedeutung des Arguments gut beschreibt. Und man sollte sich hier mindestens an die Namenskonvention von Qt halten, denn auch dort sind Namen die mit Grossbuchstaben beginnen in der Regel für Datentypen reserviert. ``def sende(self, student)`` wäre also eine gute Wahl.
Ad 2.2) Das Signal sendet nicht den Datentyp `Signal` sondern den Datentyp `Student`.
Ad 2.3) Das wird in einem Fehler enden weil `Foo`-Objekte keine `emit()`-Methode haben. Das ist eine Methode auf Signalen. Und dann stimmt das Argument von der Methode nicht. Der Name `Sig` ist nicht auf Modulebene definiert, und Du willst ja auch gar nicht eine Liste mit dem Signal-Objekt als einzigem Element verschicken, sondern doch wohl das Objekt welches der Methode übergeben wurde.
Bei `Ausgabe` gibt es dann auch wieder ein Problem, nämlich das die Methode neben dem Exemplar auf dem sie aufgerufen wird, noch den Wert übergeben bekommt, welches das Signal emmitiert, mit dem die Methode verbunden ist. Dafür gibt es aber keinen formalen Parameter in der ``def``-Zeile. Wo glaubst Du denn das der Name `Student` innerhalb der Methode her kommt? Wo wird der an einen Wert gebunden, und an welchen?
Eine Methode wird automatisch an ein Exemplar gebunden — da muss man nicht extra etwas für tun. Und wenn man sie auf einem Exemplar aufruft, wird dieses Exemplar auch automatisch als erstes Argument übergeben. Also braucht man in der Argumentliste auch einen formalen Parameter an den es dann gebunden werden kann. Per Konvention heisst der `self`.
Um mal ein bisschen pedantisch zu sein: Der Sendefunktion muss nicht der Datentyp `Student` übergeben werden, sondern ein Objekt vom Typ `Student`. `Student`, also der Datentyp ist ja selbst auch ein Objekt, aber das will man dort nicht als Wert übergeben, sondern einen konkreten Studenten.
Die Funktionssignatur kann ``def Sende(self, Student)``, ``def Sende(self, Sig)``, oder auch ``def Sende(self, Telefonbuch)`` sein. Das hat keine semantischen Auswirkungen. Man sollte einen Namen wählen, der die Bedeutung des Arguments gut beschreibt. Und man sollte sich hier mindestens an die Namenskonvention von Qt halten, denn auch dort sind Namen die mit Grossbuchstaben beginnen in der Regel für Datentypen reserviert. ``def sende(self, student)`` wäre also eine gute Wahl.
Ad 2.2) Das Signal sendet nicht den Datentyp `Signal` sondern den Datentyp `Student`.
Ad 2.3) Das wird in einem Fehler enden weil `Foo`-Objekte keine `emit()`-Methode haben. Das ist eine Methode auf Signalen. Und dann stimmt das Argument von der Methode nicht. Der Name `Sig` ist nicht auf Modulebene definiert, und Du willst ja auch gar nicht eine Liste mit dem Signal-Objekt als einzigem Element verschicken, sondern doch wohl das Objekt welches der Methode übergeben wurde.
Bei `Ausgabe` gibt es dann auch wieder ein Problem, nämlich das die Methode neben dem Exemplar auf dem sie aufgerufen wird, noch den Wert übergeben bekommt, welches das Signal emmitiert, mit dem die Methode verbunden ist. Dafür gibt es aber keinen formalen Parameter in der ``def``-Zeile. Wo glaubst Du denn das der Name `Student` innerhalb der Methode her kommt? Wo wird der an einen Wert gebunden, und an welchen?
Hallo, sorry war ne Woche weg und konnt deswegen nicht schneller antworten....
Ich fange mal von unten an auf deinen Beitrag zu antworten.
1:
Also zur Ausgabe:
Ich dachte das diese Methode automatisch weiß welches Signal sie bekommt. Wenn die Methode "Ausgabe" das wüßte, dachte ich, dass man ihr die Argumente nicht noch extra übergeben muss. Aber ist schon klarer wenn man dieser Methode student als Argument übergibt...
So siehts jetzt aus:
Jetzt denke ich müßte der Ausgabe-Methode klar sein was zu printen ist.....
2: Ok, das habe ich auch nicht gewußt weil in der Doku nie ein Objekt eines Types emitiert wird....
Was mich hier nur verwundert ist das der Sende-Methode ja eigenltich ein Objekt vom Typ Student übergeben muss wie du geschrieben hast.
Eigenltich will ich ja aber der Sende-Methode nur ein Signal übergeben das ja dann das Objekt vom Typ Student beinhaltet....
Zu deinem Vorschlag (ad 2.2) habe ich dann folgendermaßen geändert....
Zu deinem ersten Absatz:
Also ich glaube ich mir ist immer noch nicht 100% klar was das soll. Wenn ich self.Sig() schreibe wird nach der Methode in dem Exemplar gesucht, ohne self wird auf Modulebene.... Hast ja auch so geschrieben....
Find ich komisch weil wenn ich eine Methode innerhalb einer Klasse definiere, möchte ich ja eigenltich immer, dass die Methode zu allen Exemplaren dieser Klasse gehört.
Naja, jetzt kommt momentan im Code keine Fehlermeldung mehr, aber funktionieren tuts auch nicht weil nichts ausgegeben wird....
Ich stell mal den kompletten Code von der Foo-Klasse rein
Woran liegt dasw jetzt? Ich denke der Grund ist, das nichts emitiert wird... In der Doku gibts kein Bsp wo ein Objekt emitiert wird... In verschiedenen Beiträgen hier im Forum hab ich aber den Befehl so "self.emit(QtCore.SIGNAL('Sig'))" und so "self.emit(QtCore.SIGNAL("Sig"))" gesehen...
Hab das Gefühl das wenn ich den Befehl in "Sig" oder 'Sig' schreibe wird anstelle des Objekts ein String übergeben. Dann ist klar das nichts passiert.... Ohne "" und '' kommt aber wieder eine Fehlermeldung das er Sig nicht findet.....
Viele Grüße Cascoin
Ich fange mal von unten an auf deinen Beitrag zu antworten.
1:
Also zur Ausgabe:
Ich dachte das diese Methode automatisch weiß welches Signal sie bekommt. Wenn die Methode "Ausgabe" das wüßte, dachte ich, dass man ihr die Argumente nicht noch extra übergeben muss. Aber ist schon klarer wenn man dieser Methode student als Argument übergibt...
So siehts jetzt aus:
Code: Alles auswählen
def Ausgabe(self, student):
print Student.name
2: Ok, das habe ich auch nicht gewußt weil in der Doku nie ein Objekt eines Types emitiert wird....
Code: Alles auswählen
def Sende(self, student):
self.emit(QtCore.SIGNAL('self.Sig'))
Eigenltich will ich ja aber der Sende-Methode nur ein Signal übergeben das ja dann das Objekt vom Typ Student beinhaltet....
Zu deinem Vorschlag (ad 2.2) habe ich dann folgendermaßen geändert....
Code: Alles auswählen
Sig = pyqtSignal(Student) # Definiert die Art meines Signals
Also ich glaube ich mir ist immer noch nicht 100% klar was das soll. Wenn ich self.Sig() schreibe wird nach der Methode in dem Exemplar gesucht, ohne self wird auf Modulebene.... Hast ja auch so geschrieben....
Find ich komisch weil wenn ich eine Methode innerhalb einer Klasse definiere, möchte ich ja eigenltich immer, dass die Methode zu allen Exemplaren dieser Klasse gehört.
Naja, jetzt kommt momentan im Code keine Fehlermeldung mehr, aber funktionieren tuts auch nicht weil nichts ausgegeben wird....
Ich stell mal den kompletten Code von der Foo-Klasse rein
Code: Alles auswählen
class Foo(QObject):
def __init__(self, parent=None):# Konstruktor
QObject.__init__(self, parent)
self.Connection_SAS() # Verbindet Signal&Slot
Sig = pyqtSignal(Student) # Definiert die Art meines Signals
def Connection_SAS(self): #Verbindung von meinem Signal zur Ausgabe/Slot
self.Sig.connect(self.Ausgabe)
def Sende(self, student): #Sendet Signal
self.emit(QtCore.SIGNAL('Sig'))
def Ausgabe(self, student): #Ausgabe
print student.name
Hab das Gefühl das wenn ich den Befehl in "Sig" oder 'Sig' schreibe wird anstelle des Objekts ein String übergeben. Dann ist klar das nichts passiert.... Ohne "" und '' kommt aber wieder eine Fehlermeldung das er Sig nicht findet.....
Viele Grüße Cascoin
Zuletzt geändert von Cascoin am Dienstag 28. Juni 2011, 13:36, insgesamt 1-mal geändert.
@Cascoin: Ad 1) Methoden wissen nichts automatisch, mal von der Magie mit dem ersten Argument abgesehen was man bei gebundenen Methoden beim Aufruf nicht explizit übergeben muss. Signale und Slots aus Qt kennt die Sprache auch nicht, da verhält sich die Sprache also nicht plötzlich anders als bei ganz normalen Objekten und Methoden-Aufrufen. Wenn man einen Namen innerhalb einer Funktion oder Methode verwendet, dann muss der entweder dort gebunden worden sein, als Argument herein kommen, oder auf Modulebene vorhanden sein. (Einige wenige Namen stehen auch wirklich global über das `__builtin__`-Modul zur Verfügung.)
Ad 2) Beim Punktoperator auf ein Exemplar wird das Attribut erst auf dem Exemplar gesucht, und wenn es dort nicht gefunden wird, dann wird in den Klassen-Objekten gesucht, die zur Vererbungshierarchie des Objekts gehören. Alles was in einer Klasse definiert ist, kann man also auch auf Exemplaren finden.
In der Doku stehen `emit()`-Aufrufe und auch welche mit Objekten, also natürlich auch Objekte eines Typs, denn *jedes* Objekt hat einen Typ. Es gibt kein Objekt bei dem die `type()`-Funktion keinen Rückgabewert liefert.
Ich weiss nicht ob das da überhaupt so funktioniert, weil das ja eigentlich der alte Stil ist, den Du jetzt mit dem neuen mischst. Ich würde nicht `QObject.emit()` verwenden, sondern die `emit()`-Methode auf dem Signal selbst. Ist auch wieder weniger Tipparbeit. Und dann fehlt auch wieder das verschicken des `student`-Exemplars. Du scheinst da schon wieder darauf zu hoffen, dass Python Gedanken lesen kann und schon automatisch das macht, was Du gerne hättest, aber nicht explizit sagst. So funktioniert programmieren nicht. Du möchtest das Signal `Sig` mit dem Studenten als Datum emmitieren. Das muss man auch *genau so* schreiben und nicht hoffen das irgend ein Teil davon schon richtig von Python erraten wird.
Ad 2) Beim Punktoperator auf ein Exemplar wird das Attribut erst auf dem Exemplar gesucht, und wenn es dort nicht gefunden wird, dann wird in den Klassen-Objekten gesucht, die zur Vererbungshierarchie des Objekts gehören. Alles was in einer Klasse definiert ist, kann man also auch auf Exemplaren finden.
In der Doku stehen `emit()`-Aufrufe und auch welche mit Objekten, also natürlich auch Objekte eines Typs, denn *jedes* Objekt hat einen Typ. Es gibt kein Objekt bei dem die `type()`-Funktion keinen Rückgabewert liefert.
Ich weiss nicht ob das da überhaupt so funktioniert, weil das ja eigentlich der alte Stil ist, den Du jetzt mit dem neuen mischst. Ich würde nicht `QObject.emit()` verwenden, sondern die `emit()`-Methode auf dem Signal selbst. Ist auch wieder weniger Tipparbeit. Und dann fehlt auch wieder das verschicken des `student`-Exemplars. Du scheinst da schon wieder darauf zu hoffen, dass Python Gedanken lesen kann und schon automatisch das macht, was Du gerne hättest, aber nicht explizit sagst. So funktioniert programmieren nicht. Du möchtest das Signal `Sig` mit dem Studenten als Datum emmitieren. Das muss man auch *genau so* schreiben und nicht hoffen das irgend ein Teil davon schon richtig von Python erraten wird.
Code: Alles auswählen
def Sende(self, student):
self.Sig.emit(student)
Hallo,
also wenn ich das was du mir geschrieben hast verwende funktioniert es so wie ich es mir vorgestellt habe!!!! Hammergeil.....
Ich poste grad mal den kompletten Code....
Das Importzeugs:
Hier meine Beispielklasse:
Meine Foo Klasse:
und zu guter Letzt noch die main()-Funktion:
Also ich glaube das verschicken habe ich nicht vergessen, die Sende-Methode rufe ich in meiner Main() auf.... Kann man ja auch so machen.... Wie gesagt, es klappt..... Herzlichsten Dank!
Da ich das besagte Programm sauber korrigieren möchte, sodass es noch die nächsten Updates übersteht wollte ich fragen an welchen Stellen ich noch den alten mit dem neuen Style gemixt habe? Das mag ich noch ausmerzen....
mfg Cascoin
also wenn ich das was du mir geschrieben hast verwende funktioniert es so wie ich es mir vorgestellt habe!!!! Hammergeil.....
Ich poste grad mal den kompletten Code....
Das Importzeugs:
Code: Alles auswählen
from PyQt4.QtCore import *
from PyQt4 import QtGui, QtCore
import sys
Hier meine Beispielklasse:
Code: Alles auswählen
class Student(QObject): # Testklasse
def __init__(self, name, Studium, Nr):
QObject.__init__(self)
self.Name = name
self.Fach = Studium
self.Matrikel = Nr
Code: Alles auswählen
class Foo(QObject):
def __init__(self, parent=None):# Konstruktor
QObject.__init__(self, parent)
self.Connection_SAS() # Verbindet Signal&Slot
Sig = pyqtSignal(Student) # Definiert die Art meines Signals
def Connection_SAS(self): #Verbindung von meinem Signal zur Ausgabe/Slot
self.Sig.connect(self.Ausgabe)
def Sende(self, student): #Sendet Signal
self.Sig.emit(student)
def Ausgabe(self, student): #Ausgabe
print student.Name + " " + student.Fach
Code: Alles auswählen
def main(): # Main
Andi = Student("Andi", "MB", 23523)
Test = Foo()
Test.Sende(Andi)
Da ich das besagte Programm sauber korrigieren möchte, sodass es noch die nächsten Updates übersteht wollte ich fragen an welchen Stellen ich noch den alten mit dem neuen Style gemixt habe? Das mag ich noch ausmerzen....
mfg Cascoin
hallo,
noch eine kleine Frage hätte ich.
Und zwar wenn ich über diese Definition
noch
geschrieben,
also im Prinzip sieht das dann komplett so aus:
Meine Frage ist nun was das bringt, und ob das unbedingt notwendig ist?
In der Doku steht ja das es manchmal benötigt wird um eine Python-Methode explizit als Qt-Slot zu markieren um C++-Signaturen zu unterstützen.
Brauche ich das also nur wenn ich C++-Code in meinem Program habe? So verstehe ich das jedenfalls.
Unter einer C++-Signatur verstehe ich die formale Schnittstelle einer Funktion in C++ (steht so in Wiki)
Falls ich keinen C++ Code habe, ist das dann komplett sinnlos?
mfg Cascoin
noch eine kleine Frage hätte ich.
Und zwar wenn ich über diese Definition
Code: Alles auswählen
def Ausgabe(self, student):
Code: Alles auswählen
@pyqtSlot(Student)
also im Prinzip sieht das dann komplett so aus:
Code: Alles auswählen
@pyqtSlot(Student)
def Ausgabe(self, student): #Ausgabe
...................
...................
In der Doku steht ja das es manchmal benötigt wird um eine Python-Methode explizit als Qt-Slot zu markieren um C++-Signaturen zu unterstützen.
Brauche ich das also nur wenn ich C++-Code in meinem Program habe? So verstehe ich das jedenfalls.
Unter einer C++-Signatur verstehe ich die formale Schnittstelle einer Funktion in C++ (steht so in Wiki)
Falls ich keinen C++ Code habe, ist das dann komplett sinnlos?
mfg Cascoin
"pyqtSlot()" wird vor allem deswegen benötigt, um Slots automatisch über ihren Namen zu verbinden. Wiewohl es nicht schadet, "pyqtSlot()" zu benutzen, es ist im Regelfall überflüssig.
Ach wenn mir erst ein paar Seiten PyQT4 bzw. PySide gegönnt hatte, hier mein Senf:
M.E. synthetisiert dieses Beispiel die Anmerkungen der letzten 3 Seiten dieses Threads.
Grüße ... Heiko
Code: Alles auswählen
#!/usr/bin/env python
# coding: utf-8
import functools
import sys
from PyQt4 import QtGui
def print_the_message(message):
print('Button says: ' + message)
def main():
buttons = ('Hello World', 'Thanks for all the fish', '42',
'Lets go to the stoning!')
app = QtGui.QApplication(sys.argv)
layout = QtGui.QVBoxLayout()
widget = QtGui.QWidget()
widget.setLayout(layout)
widget.setWindowTitle('Buttons and partial')
for name in buttons:
button = QtGui.QPushButton(name, widget)
button.clicked.connect(functools.partial(print_the_message, name))
layout.addWidget(button)
widget.show()
app.exec_()
if __name__ == '__main__':
main()
Grüße ... Heiko
"Du bist der Messias! Und ich muss es wissen, denn ich bin schon einigen gefolgt!"
Hoi,
jetzt müßte ich doch nochmal was fragen....
Und zwar zu dem letzten Beispiel das ich reingestellt habe.... Soweit funktioniert das ja super....
Was ich jetzt grad allerdings probiere funktionert wieder nicht. Und zwar möchte ich die Sende-Methode auslagern. Und zwar in ein anderes Modul/Datei.
Wenn ich das mache, muß ich ja diese Methode in eine andere Klasse schreiben... Das Problem ist jetzt allerdings, dass diese Klasse(die die Sende Methode enthält) ja dann das Signal nicht kennt.... Das ist ja auch klar.... Jetzt frag ich mich wie ich dieser Klasse die Information übergebe, dass das Signal in einer anderen Klasse steht und schon definiert wurde.... Ich möchte das so einfach wie möglich gestalten... Soll ich der neuen Klasse(enthält die Sende-Methode) nun die Klasse übergeben in der das Signal definiert ist oder gibts da elegantere Möglichkeiten?
Angenommen ich übergebe der Sende-Klasse diejenige Klasse(hier: Foo) die das Signal enthält, dann hab ich da kurz eine Frage:
Prinzipiell funktioniert das bei mir und sieht so aus:
Jetzt hätte ich es lieber so, dass es folgendermaßen ausschaut:
-> wenn ich das so allerdings schreibe kennt er Foo nicht..... In dem obrigen Code funktionierts allerdings.....
Also meine Fragen:
1. Kann man das ganze Problem auch simpler gestalten oder muss ich immer Klassen an andere Klassen übergeben.
2. Was muss ich an meinem 2ten Codeschnippsel ändern damit das so funktioniert?
Hoffentlich hab ich mich nicht zu kompliziert ausgedrückt....
(Falls ihr euch fragt warum ich das jetzt komplizierter wie nötig mache liegt das daran das ich immer noch versuche etwas analoges zu einem Programm herzustellen das ich eigentlich korrigieren soll)
beste Grüße
Cascoin
jetzt müßte ich doch nochmal was fragen....
Und zwar zu dem letzten Beispiel das ich reingestellt habe.... Soweit funktioniert das ja super....
Was ich jetzt grad allerdings probiere funktionert wieder nicht. Und zwar möchte ich die Sende-Methode auslagern. Und zwar in ein anderes Modul/Datei.
Wenn ich das mache, muß ich ja diese Methode in eine andere Klasse schreiben... Das Problem ist jetzt allerdings, dass diese Klasse(die die Sende Methode enthält) ja dann das Signal nicht kennt.... Das ist ja auch klar.... Jetzt frag ich mich wie ich dieser Klasse die Information übergebe, dass das Signal in einer anderen Klasse steht und schon definiert wurde.... Ich möchte das so einfach wie möglich gestalten... Soll ich der neuen Klasse(enthält die Sende-Methode) nun die Klasse übergeben in der das Signal definiert ist oder gibts da elegantere Möglichkeiten?
Angenommen ich übergebe der Sende-Klasse diejenige Klasse(hier: Foo) die das Signal enthält, dann hab ich da kurz eine Frage:
Prinzipiell funktioniert das bei mir und sieht so aus:
Code: Alles auswählen
class Klasse_Sende(QObject):
def __init__(self, Foo, student): # Konstruktor dem eine Klasse Foo und Sende übergeben wird.
QObject.__init__(self)
Foo.Sig.emit(student) # In der Klasse Foo ist das Signal definiert, die Klasse student soll emittiert werden
Code: Alles auswählen
class Klasse_Sende(QObject):
def __init__(self, Foo, student): # Konstruktor dem eine Klasse Foo und Sende übergeben wird.
QObject.__init__(self)
self.sende(student)
def sende(self, student)
Foo.Sig.emit(student) # In der Klasse Foo ist das Signal definiert, die Klasse student soll emittiert werden
Also meine Fragen:
1. Kann man das ganze Problem auch simpler gestalten oder muss ich immer Klassen an andere Klassen übergeben.
2. Was muss ich an meinem 2ten Codeschnippsel ändern damit das so funktioniert?
Hoffentlich hab ich mich nicht zu kompliziert ausgedrückt....
(Falls ihr euch fragt warum ich das jetzt komplizierter wie nötig mache liegt das daran das ich immer noch versuche etwas analoges zu einem Programm herzustellen das ich eigentlich korrigieren soll)
beste Grüße
Cascoin
@Cascoin: Ist `Foo` wirklich eine Klasse? Dann funkioniert das so in keinem der beiden Fälle richtig, weil `Sig` kein gebundenes Signal ist. Wenn man ein Exemplar aus einer Klasse erstellt, welche auf Klassenebene Signalobjekte enthält, dann wird aus diesem Signal auf dem Exemplar ein an dieses Exemplar gebundenes Signalobjekt erstellt. Jedes Exemplar emittiert ja seine eigenen Signale.
Das man die `emit()`-Methode eines Signals ausserhalb von Methoden der Klasse auf der das Signal definiert ist, aufruft, ist zumindest ungewöhnlich. Signale werden üblicherweise ja dazu benutzt um interne Zustandsänderungen eines Objekts nach aussen zu melden.
Das man die `emit()`-Methode eines Signals ausserhalb von Methoden der Klasse auf der das Signal definiert ist, aufruft, ist zumindest ungewöhnlich. Signale werden üblicherweise ja dazu benutzt um interne Zustandsänderungen eines Objekts nach aussen zu melden.
Hallo,
@BlackJack: Ok, das habe ich verstanden. Dann möchte ich ein gebundenes Signal erstellen....
Dazu "rudere" ich am besten einen Schritt zurück und poste nochmal meinen älteren Code, also den Code in dem die ganze Prozedur in einer Datei steht:
Also das senden eines Exemplars (einer Klasse) von einem anderen Exemplar einer anderen Klasse aus:
Also hier der Code:
1. Die Klasse die gesendet werden soll:
2. Die Klasse in der ein Signal definiert und auf einen Slot connected wird:
3. Der main() aufruf:
Was ich jetzt wissen möchte ist, wie ich das Signal an die Klasse binde also das jede Klasse sein eigenes Signal erzeugt.
Also ich schätze das liegt an dieser Zeile:
Wenn ich allerdings:
schreibe funktioniert der Code nicht. Dann kennt der Interpreter Sig nicht....
Ich hab mir dann gedacht das es so funktionieren könnte:
und dann hätte ich den Methodenaufruf in den Konstruktor geschrieben. Im Prinzip analog zur Connect_SAS()-Methode.
Allerdings funktioniert das auch nicht und deswegen bräuchte ich nochmals etwas Hilfe.
Was ich noch dazu sagen möchte ist, dass ja in meinen Code "Sig = ..." nicht an die Klasse gebunden ist. Allerdings schreibe ich (im Code kurz drunter) "self.Sig.emit(student)" wo ich ja dann doch self schreibe, was ja für mich gebunden heißt.... Wo liegt jetzt der Zusammenhang zwischen beiden Signal? Sind diese unterschiedlich?
Hast du(oder jemand anderes) nen Tipp wie da die Syntax funktioniert sodass ich ein Signal binden kann?
Danke soweit und einen schönen Tag
mfg Cascoin
@BlackJack: Ok, das habe ich verstanden. Dann möchte ich ein gebundenes Signal erstellen....
Dazu "rudere" ich am besten einen Schritt zurück und poste nochmal meinen älteren Code, also den Code in dem die ganze Prozedur in einer Datei steht:
Also das senden eines Exemplars (einer Klasse) von einem anderen Exemplar einer anderen Klasse aus:
Also hier der Code:
1. Die Klasse die gesendet werden soll:
Code: Alles auswählen
# Meine Klasse die ich senden möchte
class Student(QObject): # Testklasse
def __init__(self, name, Studium, Nr):
QObject.__init__(self)
self.Name = name
self.Fach = Studium
self.Matrikel = Nr
Code: Alles auswählen
class Foo(QObject):
Sig = pyqtSignal(Student) # Definiert die Art meines Signals
print str(type(Sig)) + " sig" # Signalart wird ausgegeben
def __init__(self, parent=None):# Konstruktor
QObject.__init__(self, parent)
self.Connection_SAS() # Verbindet Signal&Slot
def Connection_SAS(self): #Verbindung von meinem Signal zur Ausgabe/Slot
self.Sig.connect(self.Ausgabe)
print type(self.Sig)
def Sende(self, student): #Sendet Signal
self.Sig.emit(student)
@pyqtSlot(Student)
def Ausgabe(self, student): #Ausgabe
print student.Name + " " + student.Fach
Code: Alles auswählen
def main(): # Main
Andi = Student("Andi", "MB", 23523)
Test = Foo()
Test.Sende(Andi)
if __name__ == '__main__':
main()
Also ich schätze das liegt an dieser Zeile:
Code: Alles auswählen
Sig = pyqtSignal(Student)
Code: Alles auswählen
self.Sig = pyqtSignal(Student)
Ich hab mir dann gedacht das es so funktionieren könnte:
Code: Alles auswählen
#......code....
def Define_Signal():
self.Sig = pyqtSignal(Student)
Allerdings funktioniert das auch nicht und deswegen bräuchte ich nochmals etwas Hilfe.
Was ich noch dazu sagen möchte ist, dass ja in meinen Code "Sig = ..." nicht an die Klasse gebunden ist. Allerdings schreibe ich (im Code kurz drunter) "self.Sig.emit(student)" wo ich ja dann doch self schreibe, was ja für mich gebunden heißt.... Wo liegt jetzt der Zusammenhang zwischen beiden Signal? Sind diese unterschiedlich?
Hast du(oder jemand anderes) nen Tipp wie da die Syntax funktioniert sodass ich ein Signal binden kann?
Danke soweit und einen schönen Tag
mfg Cascoin