Moin,
ich habe hier einen tkinter-Frame mit mehreren Bedien- und Anzeigeelementen.
Den würde ich gerne per Schleife vervielfältigen und in einem anderen Frame verteilen.
Das geht auch soweit.
Leider kann ich aber immer nur auf den zuletzt erstellten zugreifen.
In anderen (klammerorintierten) Programmiersprachen erstellt man ja neue Instanzen per "new" und hat dann auch eindeutige "Ansprechpartner".
Wie geht man mit sowas in python um?
Es kommt weder ein Wechsel auf eine andere Programmiersprache, noch auf ein andere GUI-Framework infrage.
In anderen (klammerorintierten) Programmiersprachen erstellt man ja neue
Instanzen per "new" und hat dann auch eindeutige "Ansprechpartner".
Wie geht man mit sowas in python um?
Klasse erstellen. Instanziieren, bis der Speicher ausgeht.
Hier erzeugen wir mehrere Instanzen und merken sie uns in einer Liste:
frames = []
for i in range(5):
f = BedienFrame(hauptframe, i)
f.grid(row=i, column=0, padx=5, pady=5)
frames.append(f) # WICHTIG: Referenz speichern!
Zugriff auf eine bestimmte Instanz:
frames[2].label.config(text="Geändert!")
root.mainloop()
In Python erzeugst du Objekte einfach durch Funktions- oder Klassenaufruf (f = BedienFrame(...)).
• Du musst die Referenzen (z. B. f) in einer Liste oder einem Dictionary speichern, wenn du später wieder darauf zugreifen willst.
• Überschreibst du die Variable in der Schleife (f = ... ohne Speicherung), bleibt am Ende nur die letzte Instanz übrig.
• Zugriff erfolgt später über frames[index] oder frames_dict[name].
Wenn du lieber sprechende Namen hast, kannst du z. B. ein Dictionary verwenden:
frames = {}
for i in range(5):
frames[f"frame_{i}"] = BedienFrame(hauptframe, i)
frames[f"frame_{i}"].grid(row=i, column=0)
Dann kannst du später schreiben:
frames["frame_3"].button.config(text="Aktiviert")
In Python ersetzt du das Konzept von new durch einfaches Instanziieren und das Speichern der Referenzen (z. B. in einer Liste oder einem Dictionary).
So hast du „eindeutige Ansprechpartner“ für jede erstellte GUI-Einheit.
Das verstehe ich nicht. Du weißt offensichtlich, wie Objektorientierung mit Tkinter geht. Warum erzeugst Du Dein Hauptfenster trotzdem prozedural? Das ärgert mich schon bei den 10000 Tutorials, die im Netz herumschwirren, dort schreibt offenbar immer wieder ein neuer Tünnes von den anderen ab. Meinen Beispielcode habe ich hier angehängt.
Das Einzige, was man dabei beachten muß, wird zunehmend unwichtiger: Tkinter ist schon recht alt und unter Python2 waren das old-style classes, die also nicht von object geerbt haben. Darum hat dort super() nicht so funktioniert, wie wir das heute kennen (und oft als selbstverständlich annehmen), weil die von object geerbte Infrastruktur nicht vorhanden war. Mit dem Ausschleichen von Python2 wird das zwar zunehmend unwichtig, denn seit Python3 gibt es ja nurmehr new-style classes, die automatisch von object erben und deshalb die notwendige Infrastruktur haben. Aber wenn man mal alten Code pflegen müsste und den aus irgendeinem Grund nicht auf Python3 portieren könnte oder wollte, ist es sinnvoll, das im Hinterkopf zu behalten.
1
> frames = []
2
> for i in range(5):
3
> f = BedienFrame(hauptframe, i)
4
> f.grid(row=i, column=0, padx=5, pady=5)
5
> frames.append(f) # WICHTIG: Referenz speichern!
6
>
Da würde ich eine List Comprehension eleganter finden:
1
#!/usr/bin/env python # for proper syntax highlighting
Das ärgert mich schon bei den 10000 Tutorials, die im Netz
herumschwirren, dort schreibt offenbar immer wieder ein neuer Tünnes von
den anderen ab
Dann schreib doch endlich mal eins, das dem mmodernen Standard entspricht und laber nicht immer in irgendwelchen Threads rum, wie du es machen würdest (Sätze, die mit "Ich würde.." beginnen, stellen mir die Nackenhaare auf, weil die implizieren, dass alle Welt das selbe weiß wie du).
Du könntest ja beispielsweise mal einen Artikel hier in der Artikelsammlung deses Forums erstellen, wenn du schon so eine Korypäe bist.
Dann brauchst du nur auf deinen Artikel verweisen.
In Python erzeugst du Objekte einfach durch Funktions- oder
Klassenaufruf (f = BedienFrame(...)).
• Du musst die Referenzen (z. B. f) in einer Liste oder einem
Dictionary speichern, wenn du später wieder darauf zugreifen willst.
• Überschreibst du die Variable in der Schleife (f = ... ohne
Speicherung), bleibt am Ende nur die letzte Instanz übrig.
• Zugriff erfolgt später über frames[index] oder frames_dict[name].
Wenn du lieber sprechende Namen hast, kannst du z. B. ein Dictionary
verwenden:
Dann schreib doch endlich mal eins, das dem mmodernen Standard
entspricht und laber nicht immer in irgendwelchen Threads rum, wie du es
machen würdest (Sätze, die mit "Ich würde.." beginnen, stellen mir die
Nackenhaare auf, weil die implizieren, dass alle Welt das selbe weiß wie
du).
Schau doch einfach in den Anhang meines Beitrages, den Du wieder einmal in Deiner Dir ganz eigenen Höflichkeit beantwortet hast. Da ist sogar ein Link "Codeansicht", den Du bemühen kannst. Du schaffst das, ich glaube an Dich!
Ich wünsche Dir viel Glück und allen einen schönen Sonntag.
Schau doch einfach in den Anhang meines Beitrages, den Du wieder einmal
in Deiner Dir ganz eigenen Höflichkeit beantwortet hast. Da ist sogar
ein Link "Codeansicht", den Du bemühen kannst. Du schaffst das, ich
glaube an Dich!
Arrogant bist du gar nicht, oder?
Ich hatte dir einen Vorschlag gemacht, weil du ja immer von allem so genervt bist, dich alle anderen immer aufregen und dauernd mit deinem Wissen prahlen musst, es dann aber auch jedes Mal wieder hinbschreiben musst.
Wü+rdest du das in einem Artikel in der Artikelsammlung veröffentlich, bräuchtest du höchstens den Link dazu verteilen (das könnten dann überigens auch andere machen, die den Artikel vielleicht gut finden).
Warum ich deine Art nicht mag, habe ich dir geschrieben.
Wenn dich meinne "höfliche Art" stört: Bleib weg (von Threads, die ich eingestellt habe).
Mich interessiert deine Meinung kein Stück, und helfen konntest du ja auch bisher nicht.
Edit: Dein Quellcode ist ja super kommentiert. Da kann man richtig was lernen. NOT
Das ist eine außerordentlich witzige Frage von jemandem, der hier erst um Hilfe bittet und dann die Helfer verspottet. :-)
Edit: Dein Quellcode ist ja super kommentiert. Da kann man richtig was
lernen. NOT
Mein Vorposter hatte schon gezeigt, daß er das Thema grundsätzlich verstanden und nur eine kleine Anregung gebraucht hat. Er wird meinen Anhang sicher auch ohne Kommentare verstehen, und alles Übrige steht in meinem Beitrag.
Schau, ich habe verstanden, daß Du Python nicht leiden kannst und Du trotzdem von irgendwem dazu gezwungen wirst, etwas damit zu machen. Aber auch wenn mir das leid tut, bin ich der Falsche, um Deinen Frust darüber auszulassen.
Schau, ich habe verstanden, daß Du Python nicht leiden kannst und Du
trotzdem von irgendwem dazu gezwungen wirst, etwas damit zu machen. Aber
auch wenn mir das leid tut, bin ich der Falsche, um Deinen Frust darüber
auszulassen.
Das hast du falsch verstanden.
Ich mag Sätze, die mit "Ich würde..." beginnen, einfach nicht.
Soll ich deiner Meinung nach das Projekt noch mal von vorne beginnen, um mir vorher noch dein Wissen anzueignen?
Wie wärw denn eine Formulierung wie "Vorschlag fürs nächste Mal...".
Vielleicht übernehme ich beim nächsten Projekt ja deinen Vorschlag. Aber jetzt ist es dafür zu spät ("Never change a running system!").
Deine "Hilfe" mit ".after" in anderen Python-Thread war auch nicht wirklich hilfreich. Dafür hatte ich aber in meiner "typisch freundlichen Art" ("höflich" ist mMn unpassend, da durch Höflichkeitsbremser noch negativer belegt) schon bedankt.
Schau, ich habe verstanden, daß Du Python nicht leiden kannst und Du
trotzdem von irgendwem dazu gezwungen wirst, etwas damit zu machen. Aber
auch wenn mir das leid tut, bin ich der Falsche, um Deinen Frust darüber
auszulassen.
Das hast du falsch verstanden.
Okay.
Ich mag Sätze, die mit "Ich würde..." beginnen, einfach nicht.
Wie wärw denn eine Formulierung wie "Vorschlag fürs nächste Mal...".
Naja, "ich würde" sagt und zeigt ja, wie ich das machen würde, also implizit mit meinem Wissen, und meiner Erfahrung. Die Formulierung, die Du vorschlägst, empfinde ich hingegen, als würde mein alter Meister zum Lehrling sprechen.
Soll ich deiner Meinung nach das Projekt noch mal von vorne beginnen, um
mir vorher noch dein Wissen anzueignen?
Das kommt darauf an, ehrlich gesagt. Das Ziel der Übung sollte IMHO bleiben, am Ende eine Codebasis zu erhalten, die natürlich erstens tun muß, was sie tun soll, und zweitens möglichst les- und wartbar ist. Dabei stehen drittens auch immer die Fragen nach Ökonomie und Priorisierung im Raum.
Vielleicht übernehme ich beim nächsten Projekt ja deinen Vorschlag. Aber
jetzt ist es dafür zu spät ("Never change a running system!").
Puh... "never change a running system" ist für einen DevOpsler schwer zu verknusen, denn changing running systems ist ja quasi mein Beruf.
Deine "Hilfe" mit ".after" in anderen Python-Thread war auch nicht
wirklich hilfreich. Dafür hatte ich aber in meiner "typisch freundlichen
Art" ("höflich" ist mMn unpassend, da durch Höflichkeitsbremser noch
negativer belegt) schon bedankt.
Das stimmt, allerdings... wenn Du häufiger mit Tkinter arbeitest, wirst Du Dich garantiert noch an diesen Rat erinnern. Spätestens dann, wenn Du eine Anzeige aktualisieren möchtest und sich nichts tut, obwohl Du genau weißt, alles richtig zu machen. ;-)
Naja, "ich würde" sagt und zeigt ja, wie ich das machen würde, also
implizit mit meinem Wissen, und meiner Erfahrung.
Genau so verstehe ich diese Formulierung auch.
Ein kleines Beispiel (jetzt klinge ich wie mein Vater), warum ich diese Aussage nicht so pralle finde:
Ich hatte mir einen Hochdachkombi in der Lieferwagen-Version gekauft, da ich zu dem Zeit öfter mal Gerätschaften transportiert habe.
Eine Bekannte meinte dann "Ich würde mir den ja zum Wohnmobil umbauen." - "Du würdest dir den nicht mal kaufen."
Oder jemand sagt "Ich würde das ja so und so machen!" - "Dann mach das doch selber!"
Die Formulierung, die
Du vorschlägst, empfinde ich hingegen, als würde mein alter Meister zum
Lehrling sprechen.
Und? Was spricht dagegen? Solange man nicht auf dem selben Stand ist (dass ich keine Ahnung von python habe, hatte ich schon geschrieben), aber jemanden frage, der mehr Ahnung hat, ist das ein Meister-/Geselle-Lehrlingsverhältnis bzw. Lehrer-Schüler-Verhältnis.
[/Offtopi]
Die Formulierung, die
Du vorschlägst, empfinde ich hingegen, als würde mein alter Meister zum
Lehrling sprechen.
Und? Was spricht dagegen? Solange man nicht auf dem selben Stand ist
(dass ich keine Ahnung von python habe, hatte ich schon geschrieben),
aber jemanden frage, der mehr Ahnung hat, ist das ein
Meister-/Geselle-Lehrlingsverhältnis bzw. Lehrer-Schüler-Verhältnis.
[/Offtopi]
Ich bin hier (soweit ich weiß) niemandes Chef und will das auch nicht sein, und ich möchte so etwas auch nicht einmal andeuten. Deine Formulierung gibt mir das Gefühl, ich spräche als Chef zu meinem Mitarbeiter, als mein "schau bitte mal auf mein Beispiel, ob Dir das nicht auch besser gefällt".
Warum erzeugst Du Dein Hauptfenster trotzdem
prozedural? Das ärgert mich schon bei den 10000 Tutorials, die im Netz
herumschwirren, dort schreibt offenbar immer wieder ein neuer Tünnes von
den anderen ab.
Weil es in solchen Situationen oft dazu kommt, dass man zwar ähnliche Inhalte, aber nicht die gleichen verwendet. Objektorientierung erzeugt gleiche Objekte, die aber mit einer Parametrisierung angepasst werden können. Theoretisch könnte man die Objekte jetzt so gestalten, das die Parametrisierung diese Unterschiede mit abdeckt.
Leider ist es aber oft so, dass man erst beim Erstellen eines Programmes die vielen kleinen Nickeligkeiten erkennt, die die Unterschiede verlangen. Jetzt nachträglich immer wieder das Objekt anpassen, kann kompliziert und vor allem langwierig werden.
Irgendwann ist dann der Punkt gekommen, wo es schneller geht, statt ein Objekt anzupassen, per copy und paste eine Kopie zu machen und separat in das Programm einzufügen.
Wenn Du hauptberuflich Python schreibst, mag das anders aussehen, aber gerade Python ist eine Sprache, die wegen ihrer Einfachheit von vielen Programmierern verwendet wird, die eher selten oder sogar nur als Hobby gelegentlich etwas programmieren.
Als solcher muss ich mich nach einem halben oder ganzen Jahr, wenn ich alles vergessen habe, wieder neu in die Details der Sprache bzw. meines eigenen Programmes einarbeiten, und da ist dann Objektorientierung auf einmal etwas umständlich. Copy and paste ist dann durchaus die einfachere Alternative und führt zu dem prozeduralen Stil.
Wenn Du bessere Alternativen kennst, die auch meine eigenen diesbezüglichen Unzulänglichkeiten abdecken, so bin ich auf Deine Vorschläge gespannt.
Nachtrag: Sehr viele der Eigenschaften, die Python so "einfach" machen, betreffen Fälle, wo durch Schleifen und Vereinbahrung vieles "automatisiert" werden kann. Diese Fälle sind aber nur hilfreich, wenn ich ständig damit arbeite. Als Gelegenheitsprogrammierer verstolpere ich dort nur.
Warum erzeugst Du Dein Hauptfenster trotzdem
prozedural? Das ärgert mich schon bei den 10000 Tutorials, die im Netz
herumschwirren, dort schreibt offenbar immer wieder ein neuer Tünnes von
den anderen ab.
Weil es in solchen Situationen oft dazu kommt, dass man zwar ähnliche
Inhalte, aber nicht die gleichen verwendet. Objektorientierung erzeugt
gleiche Objekte, die aber mit einer Parametrisierung angepasst werden
können. Theoretisch könnte man die Objekte jetzt so gestalten, das die
Parametrisierung diese Unterschiede mit abdeckt.
Ohne konkretes Beispiel ist es natürlich nicht ganz einfach, etwas in Code zu zeigen. Aber die Objektorientierung bietet doch neben der Parametrierung noch eine andere Möglichkeit zur Spezialisierung, nämlich die Vererbung. Vielleicht magst Du dazu einen eigenen Thread eröffnen und mit einem (oder gern mehreren) Codebeispielen zeigen, was genau Du meinst?
Irgendwann ist dann der Punkt gekommen, wo es schneller geht, statt ein
Objekt anzupassen, per copy und paste eine Kopie zu machen und separat
in das Programm einzufügen.
Wenn ich so etwas klassisch prozedural schreibe, wie es zum Beispiel auf der (ansonsten sehr empfehlenswerten) Seite Realpython [1] gezeigt wird, muß ich beim Copy'n'Paste mehrere Zeilen kopieren, die Variablennamen in einer Reihe meiner kopierten Codezeilen anpassen, und wenn ich dabei eine Zeile vergesse oder einen Variablennamen nicht oder nicht richtig anpasse, kann ich enormes Glück haben und die Veranstaltung explodiert sofort. Mit ein wenig Pech habe ich einen sehr schwer zu findenden Fehler eingebaut.
Schau Dir auf der verlinkten Seite [1] einfach mal unten den "Text Editor" an (letztes Beispiel vor "Conclusion"): fünf globale Variablen auf nur 37 Zeilen Code in einem winzigen Projekt. Ich hab' mir mal den Spaß gemacht, und dieses Beispiel in zwei OO-Versionen umgebaut: einmal in better.py so "halbwegs OO", wie ich das in einem kleinen Projekt wie diesem umgesetzt hätte. Zudem einmal in best.py, wo auch für den Frame mit den Buttons eine eigene Klasse benutzt wird -- was bei diesem Winzling natürlich Overkill ist, aber in einem großen Projekt würde das durch die bessere Organisation des Code den Überblick, und damit die Les- und Wartbarkeit deutlich verbessern. Den Originalcode von der verlinkten Seite habe ich der Einfachheit halber als main.py angehängt.
Für jeden, der Interesse an der Entwicklung mit Tkinter hat, ist die Seite trotzdem ausgesprochen lesenswert, auch wenn ich mit dem prozeduralen Stil ihres Autors unglücklich bin. Dennoch ist die Seite großartig!
Wenn Du hauptberuflich Python schreibst, mag das anders aussehen, aber
gerade Python ist eine Sprache, die wegen ihrer Einfachheit von vielen
Programmierern verwendet wird, die eher selten oder sogar nur als Hobby
gelegentlich etwas programmieren.
Naja, auch wenn man kein hauptberuflicher Entwickler ist -- was ich nicht bin und auch nie gewesen bin, ich komme aus dem Operationsbereich -- ist es immer sinnvoll, sauberen und sauber strukturierten Code zu schreiben, den man auch morgen noch lesen und viel leichter anpassen, warten und pflegen kann. Dabei hilft die Objektorientierung auch den Nichtprofis enorm. Wie gesagt, schau' Dir den angehängten Code an: findest Du denn nicht auch, daß meine Varianten viel strukturierter und übersichtlicher sind?
Hinzu käme bei einem wirklich großen Projekt, daß ich meinen Code ganz leicht auf mehrere Dateien verteilen kann. Das ist mit dem prozeduralen Originalcode von Realpython leider nicht möglich.