Threads: PostEvent und Return

Plattformunabhängige GUIs mit wxWidgets.
Benutzeravatar
DatenMetzgerX
User
Beiträge: 398
Registriert: Freitag 28. April 2006, 06:28
Wohnort: Zürich Seebach (CH)

Threads: PostEvent und Return

Beitragvon DatenMetzgerX » Montag 5. Juni 2006, 14:54

Hallo...

Aufruf

Code: Alles auswählen

Value = wx.PostEvent(frame, GetValue())



Code: Alles auswählen

class GetValue(wx.PyEvent):
    def __init__(self):
        wx.PyEvent.__init__(self)
        self.SetEventType(EVT_GETVALUE_ID)


Code: Alles auswählen

    def GetValue(self, event):
       return self.Procress.GetValue()


self.Procress ist eine Gauge...

Wie kann ich es nun machen, das ich den return Value beim Aufruf zurückbekomme :roll:

Eine Globale Variable möchte ich nicht ;)

Gruess DM
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Re: Threads: PostEvent und Return

Beitragvon gerold » Montag 5. Juni 2006, 22:49

Hi DM!

Leider bekomme ich aus deiner Schilderung nicht heraus, was du überhaupt willst. Allerdings möchte ich dir nahe legen, das Kapitel über Events noch mal im Buch "wxPython in Action" nachzulesen.

Und, bitte verwende keine bereits fix zugeordneten Namen wie "GetValue" für eine benutzerdefinierte Klasse oder einen Eventnamen. Da muss man ja durcheinander kommen.

Wie ich das so aus dem Buch herauslese, läuft das mit den selbstdefinierten Events jetzt so:

Code: Alles auswählen

# Event-Klasse
class BeimKlickenEvent(wx.PyCommandEvent):
    def __init__(self, event_type, id):
        wx.PyCommandEvent.__init__(self, event_type, id)
        self.mein_parameter = None

# Event-Type und Event-Binder
myEVT_BEIM_KLICKEN = wx.NewEventType()
EVT_BEIM_KLICKEN = wx.PyEventBinder(myEVT_BEIM_KLICKEN, 1)

#...

# Irgendwo in einer Klasse: Ausloesen
def der_ausloeser(self):
    event = BeimKlickenEvent(myEVT_BEIM_KLICKEN, self.GetId())
    event.mein_parameter = 10
    self.GetEventHandler().ProcessEvent(event)
   
#...

# Irgendwo in der Klasse in der das Event gebunden werden soll
def __init__(self):
    self.Bind(EVT_BEIM_KLICKEN, self.on_beim_klicken)

def on_beim_klicken(self, event):
    der_parameter = event.mein_parameter
    print der_parameter

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
DatenMetzgerX
User
Beiträge: 398
Registriert: Freitag 28. April 2006, 06:28
Wohnort: Zürich Seebach (CH)

Beitragvon DatenMetzgerX » Dienstag 6. Juni 2006, 06:12

ich würde gerne einen Event auslösen, welcher mir dann etwas zurück gibt. Also Event aufrufen und Return Value einer Variablen zuweisen. Nur gibt wx.PostEvent(....) keine Werte zurück. Gibts da sonst irgend eine Möglichkeit (wx.CallAfter ging ebenfalls nicht)
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Dienstag 6. Juni 2006, 07:40

DatenMetzgerX hat geschrieben:Also Event aufrufen und Return Value einer Variablen zuweisen. Nur gibt wx.PostEvent(....) keine Werte zurück.

Hi DM!

Dazu sind Events nicht geschaffen worden. Events werden ausgelöst -- danach läuft das Programm weiter, ohne abzuwarten, ob etwas zurück kommt oder nicht. Die einzige Möglichkeit, die ich in Verbindung mit Events sehe: Du definierst ein Queue-Objekt, das du über das Event übergibst und wartest sofort danach darauf, dass dir etwas über das Queue-Objekt übergeben wird.

Allerdings würde ich das nie machen, da das meiner Meinung nach die Stabilität deines Programmes extrem beeinflussen kann. Was ist, wenn dir aus irgendeinem Grund nichts über das Queue-Objekt zurück gegeben wird? Dein Programm würde unweigerlich hängen.

Du kannst beim Auslösen, Daten über die Event-Klasse an den Event-Handler (=die Funktion die das Event empfängt) übergeben. Wie das geht, habe ich oben im Beispiel bereits demonstriert. (siehe self.mein_parameter)
Allerdings ist das eine einseitige Sache. Du bekommst nichts zurück, weil das bedeuten würde, dass das Programm an dieser Stelle auf eine Rückgabe warten müsste. Dazu sind Funktionen und Methoden da. Wenn du eine Methode eines anderen Objektes aufrufst, dann wird dein Programm erst dann fortgesetzt, wenn die Methode ein Ergebnis zurück liefert.

Die Allgemeine Vorgehensweise bei Events sollte die sein, dass zuerst von einem Objekt ein Event ausgelöst wird. Der Event-Handler, arbeitet etwas ab, holt sich z.B. Informationen und ruft beim auslösenden Objekt eine Methode auf. An diese Methode werden wieder Werte übergeben, mit denen das vormals auslösende Objekt etwas anfangen soll.

Fazit: Designe dein Programm so, dass es asyncron läuft. Sollte ein Thread immer wieder neue Daten brauchen, dann übergib sie *threadsave*, also z.B. über eine Queue. Wenn du Daten von einem Thread an den Hauptthread übergeben möchtest, dann rufe mit wx.CallAfter() eine Methode deines Hauptthreads auf, an die du die Daten übergeben kannst.
Wenn du bei diesen vorgängen immer auf die Ergebnisse warten musst, dann brauchst du keine Threads.

Ich weis, dass ist alles ein wenig theoretisch, aber vielleicht hilft es dir ja weiter.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs

Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder