Kommunikation zwischen selbsterstellten Modulen

Code-Stücke können hier veröffentlicht werden.
Antworten
ippurk
User
Beiträge: 61
Registriert: Mittwoch 8. Juli 2009, 20:40

Hallöchen,

für mein Kontoführungsprojekt (hat sich inzwischen zu einer Mietshausverwaltung entwickelt), brauchte ich eine Möglichkeit, so eine Art Kontoauszug grafisch ansprechend zu präsentieren. Der User soll einzelne Kontobewegungen anwählen können, um sie nachträglich bearbeiten zu können. Das führte letztenendes leider, oder zum Glück dazu, daß, daß ich mich mit Modulen beschäftigen musste. Und dann hab ich mal eins geschrieben: http://paste.pocoo.org/show/130924/. Und das sollt ihr jetzt so richtig harsch in die Kritik nehmen. Aber eher nicht so wegen der Kleinigkeiten, sondern, ob das grundsätzlich alles sinnvoll aufgebaut ist und vor allem, ob die Speicherung der einzelnen Boxen und deren zugehörigen Dinge in einer Liste sinnvoll ist, oder überflüssig. Es gibt ja hier in dem Forum auch eine Megalistbox, die das aber irgendwie anders macht.

Die Hauptfrage allerdings ist die: Wie kriege ich jetzt in meinem Hauptprogramm, welches dieses Modul hier aufruft, eine Aktion an die Tatsache gebunden, daß ein Eintrag in dieser "Megalistbox" doppelgeklickt wird ? Dieses Event (und das Event Return) wird ja hier intern auf die Funktion "bigAction" geleitet.

Und dann noch eine Kleinigkeit: Das configureEvent des Hauptfensters muss im Moment außerhalb meines Moduls an die Funktion resize meines Moduls gebunden werden, was ich eigentlich lieber Modulintern lösen wollen würde. Ist das möglich ?

Schönen Abend noch, ippurk
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Naja, wenn du die Instanz deiner "ListBoxSpecial" hast und ein Event in deinem "Hauptprogramm" gefeuert wird, dann rufst du eben die entsprechende Methode auf.

zB:

Code: Alles auswählen

def on_foo_event(blah):
    yourbox.bigAction(blah)
Und genauso machst du das mit dem resize-Zeug:

Code: Alles auswählen

def on_resize(blah):
    yourbox.resize(blah)
Ansonsten sollte deine __init__-Methode nicht so viel machen (auslagern!) und du solltest nicht so viel mit Indexen arbeiten (selectItemAction zb). Wenn du wirklich so viel Listen-geindexe brauchst, mach dir lieber eine Klasse. Das macht das Ganze auch leichter durchschaubar. Keycodes (120 zb) solltest du in Konstanten/Variablen auslagern, der Abstraktion und Lesbarkeit wegen. Klassen sollten immer von object erben (zumindest bei Python < 3).

PEP8 beachten wäre noch ganz gut, hör mal auf mit diesem geCamelCase ;)

Grüße

PS: Kommst du von Java? ;-)
ippurk
User
Beiträge: 61
Registriert: Mittwoch 8. Juli 2009, 20:40

wow, die Antwort muss ich erst mal ne Woche lang durcharbeiten, um sie zu verstehen. Hab vor 3 Wochen oder so mit dem Programmieren angefangen, siehe erster Post. Und Java, hab ich keine Ahnung von.
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

ippurk hat geschrieben:wow, die Antwort muss ich erst mal ne Woche lang durcharbeiten, um sie zu verstehen. Hab vor 3 Wochen oder so mit dem Programmieren angefangen, siehe erster Post. Und Java, hab ich keine Ahnung von.
Oh, ok. Wer hat dir dann camelCase beigebracht? :D

PS: Wenn du was nicht verstanden hast, sag es, dann erklär ich es anfängerfreundlicher ;)
ippurk
User
Beiträge: 61
Registriert: Mittwoch 8. Juli 2009, 20:40

hm, na gut. Also, dieses camelCase hab ich, laut meiner diffusen Erinnerung in irgendeinem StyleGuide gelesen, weiß ich aber nicht mehr so genau. Ich bin da durchaus flexibel in der Gestaltung meiner Variablennamen und auch eigentlich noch auf der Suche nach einem sinnvollen Format. xy_Bla_Bal gibts ja auch. Soviel dazu.

Und jetzt zu der Eventsache:

Mein Doppelklick auf ein Megalistboxitem feuert doch kein event in meinem Hauptprogramm ab, oder versteh ich da was falsch ?

Wegen "resize": das versteh ich auch nicht. Soll ich dein def in meinem Modul einbauen oder in meinem Hauptprogramm ? Wodurch würde dein on_resize denn ausgelöst ? Eigentlich will ich in meinem Hauptprogramm sowas schreiben können wie "mybox.bind(<bigAction>, do)" oder so in der Art. Macht das nicht Sinn ?

Bezüglich meiner Arbeit mit den Indexen: Die Lesbarkeit hat mir während der Produktion meines Skripts ziemliche Sorgen bereitet. Und auch der Sinn der Tatsache, alle Dinge in Listen abzulegen. Aber wo kann ich da was einsparen ? Was meinst du damit, lieber eine Klasse zu machen, wenn ich so viele Indexe brauche ?

Ok, über die anderen Kommentare versuch ich mal selber nachzudenken.

Auf jeden Fall danke schonmal für die Auseinandersetzung mit meinem kleinen Gehirnknoten hier.
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

ippurk hat geschrieben:Ich bin da durchaus flexibel in der Gestaltung meiner Variablennamen und auch eigentlich noch auf der Suche nach einem sinnvollen Format. xy_Bla_Bal gibts ja auch. Soviel dazu.
Jo, PEP8 (google :)) sagt, man sollte eine_tolle_variable verwenden. Und EineTolleKlasse.
Und jetzt zu der Eventsache:

Mein Doppelklick auf ein Megalistboxitem feuert doch kein event in meinem Hauptprogramm ab, oder versteh ich da was falsch ?
Ich dachte, du meinst mit dem Satz
Dieses Event (und das Event Return) wird ja hier intern auf die Funktion "bigAction" geleitet.
dass du in deinem "Hauptprogramm" das schon richtig gebunden hast. Das war anscheinend nicht der Fall. Du müsstest dazu einfach mal in der TK-Dokumentation nachgucken, wie man denn einen Klick auf ein Listenitem an eine Funktion o.ä. bindet.
Wegen "resize": das versteh ich auch nicht. Soll ich dein def in meinem Modul einbauen oder in meinem Hauptprogramm ? Wodurch würde dein on_resize denn ausgelöst ? Eigentlich will ich in meinem Hauptprogramm sowas schreiben können wie "mybox.bind(<bigAction>, do)" oder so in der Art. Macht das nicht Sinn ?
Nein. Einzig das Hauptmodul weiß, wann es Zeit ist, die resize-Funktion aufzurufen, und das sollte es dann auch machen. (`mybox.resize()` eben ;)).
Bezüglich meiner Arbeit mit den Indexen: Die Lesbarkeit hat mir während der Produktion meines Skripts ziemliche Sorgen bereitet. Und auch der Sinn der Tatsache, alle Dinge in Listen abzulegen. Aber wo kann ich da was einsparen ? Was meinst du damit, lieber eine Klasse zu machen, wenn ich so viele Indexe brauche ?
Hm, dazu fehlen mir die Nerven, mich durch dein ganzes Modul durchzuackern, weil ich da einfach nicht besonders viel verstehe davon, was da gemacht wurde. Dazu kenne ich auch die TK-API zu schlecht (hab damit noch nie gearbeitet).

Aber mehrere Male `self.listeDerBoxen[spalte][0].bind(...)` zu schreiben ist nicht soo der Hammer, Mach da lieber sowas:

Code: Alles auswählen

AKTIONEN = {
    '<<Aktion1>>', funktion1,
    '<<Aktion2>>', funktion2,
    # ...
}

blah = self.listeDerBoxen[spalte][0]
for aktion, funktion in AKTIONEN.items():
    blah.bind(aktion, funktion)
Gruß
ippurk
User
Beiträge: 61
Registriert: Mittwoch 8. Juli 2009, 20:40

wollte nochmal vorsichtig auf meine erste Frage, siehe oben, hinweisen.

Inzwischen gibts allerdings auch etwas neueren Code: http://paste.pocoo.org/show/131525/
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Hatte ich doch schon gesagt, du musst in der TK-Doku schauen wie man ein "Doppelklick-auf-Listen-Item"-Event mit einer Funktion verbindet.

Gruß
ippurk
User
Beiträge: 61
Registriert: Mittwoch 8. Juli 2009, 20:40

richtig, nur das das leider meine Frage nicht beantwortet. Mein DoppelklickaufListenitemEvent ist doch schon an eine Funktion gebunden, nämlich big_action. Und ich würde hier auch nicht fragen, wenn ich nicht schon tagelang irgendwelche Dokuseiten durchgeblättert hätte. Vielleicht drücke ich mich auch zu kompliziert aus. Erst mal stell ich mir sowieso die Frage, hier totalen Quatsch produziert zu haben und zweitens gehts eigentlich um folgendes Problem:

Ich will meinen Code hier in einer etwas umfangreicheren Gui verwenden, die allerdings nur in einem Fenster abläuft, ähnlich wie eine Internetseite mit Menue links und Inhalt rechts. Diese meine Listbox könnte ich doch schön in einem Modul auslagern, dachte ich zumindest. Und was ich noch so dachte, war: Mein Modul ListBox sollte also, wenn benötigt, mit einem recht unkomlizierten Befehl wie z.B.

Code: Alles auswählen

bei Klick in Hauptmenue:
rechter_frame.mach_leer
l = l.ListBoxSpecial(rechter_frame, "liste")
l.bind('<big_action>', andere_action)
verwendbar sein. Die Ausgabe des Moduls müsste also so eine Art CustomEvent mit Namen big_action sein, was von meinem Obermodul erkannt wird und dann mit der angegebenen ListenID und der Spaltennummer halt was anderes macht, nämlich andere_action.

Kann natürlich sein , daß ich hier völlig auf dem Holzweg bin, wie gesagt, bin ziemlich neu hier und dann brauch ich jemanden, der sagt: Du machst da totalen Quatsch. Aber das sollte dann vielleicht jemand sein, der auch Tkinter versteht und nicht von sich selbst behauptet, das gar nie zu benutzen und als Empfehlung ein Nachlesen im Handbuch vorschlägt.

Und bezüglich Handbuch: Habe leider noch kein schönes Handbuch gefunden, was einem so die Grundphilosophie einer komplexeren Tk-Gui nahebringt. Vielleicht kennt da jemand was, das würd ich gern lesen.
ippurk
User
Beiträge: 61
Registriert: Mittwoch 8. Juli 2009, 20:40

und so langsam checke ich auch, daß ich wohl im falschen Unterforum gelandet bin, hier gehts wohl anscheinend eher um funktionierende Sachen und nicht um Anfängerproblemchen.
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Okay, nochmal, zum Verständnis: Dein Event (Doppelklick oder was auch immer) löst bereits aus, dass die Funktion `irgendwas` aufgerufen wird? Habe ich das jetzt richtig rausgelesen? Und du möchtest, dass dein "Hauptprogramm" auch etwas davon mitkriegt, wenn in deinem Untermodul `irgendwas` aufgerufen wird?

Wenn ja, dann bist du gerade dabei, ein Event-System aufzubauen. Du müsstest dein Das-Event-Auslösende-Modul um die Fähigkeit, fremde/externe Funktionen aufzurufen, erweitern.

Beispiel:

Code: Alles auswählen

class Blah(object):
    # (Blah ist deine "Megalistbox" und wuerde in einem Modul ausgelagert sein)
    event_register = []

    def register_event(self, callback):
        self.event_register.append(callback)

    def irgendwas(self):
        # das hier ist deine Methode, welche bei Doppelklick (o.ae.) aufgerufen
        # wird. Du moechtest jetzt, dass alle Callbacks, die in
        # event_register definiert sind, auch etwas von diesem Aufruf haben.
        # Also rufst du jede der Funktionen auf:
        print "Blah hat ein Event empfangen"
        for callback in self.event_register:
            callback()

deinemegaliste = Blah()

deinemegaliste.irgendwas()
# Doppelklick wurde ausgefuehrt, rufe die verbundene Methode auf
# (macht jetzt noch nichts)

def receive_event():
    # "empfaengt" das Event welches "Blah" ausgeloest hat
    print "Das Hauptmodul hat ein Event empfangen!"

deinemegaliste.register_event(receive_event)
deinemegaliste.irgendwas()
# Und nochmal ausfuehren, jetzt sollte "Event empfangen!" erscheinen
ippurk
User
Beiträge: 61
Registriert: Mittwoch 8. Juli 2009, 20:40

Hallo Dauerbaustelle,

meinst du so etwas in der Richtung Threading ? Ist das das richtige Wort ? Wo kann man da was drüber lesen ?
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Nein.
Antworten