Seite 1 von 1
Listbox, die nicht alles anzeigt
Verfasst: Freitag 8. April 2022, 17:30
von Üpsilon
Ich habe eine Frage, die wahrscheinlich eher eine Software-Engineering-Frage ist als eine Tkinter-Frage.
Angenommen ich habe ein Programm mit einer GUI.
Das Programm hat als Variable eine lange Liste von Objekten gespeichert. Sagen wir diese Liste heißt liste.
In der GUI ist eine Listbox. Sagen wir die Listbox heißt listbox.
Jeder Eintrag in der Listbox ist eine Beschreibung von einem der gespeicherten Objekte.
Neben der Listbox ist ein Button. Wenn der Benutzer den Button anklickt, dann soll das Objekt, das gerade in der Listbox ausgewählt ist, irgendwie geändert werden.
Um das zu erreichen, knüpfe ich an den Button eine Funktion die irgendwie sowas macht wie:
liste[listbox.curselection()[0]] = geändertes_objekt
So weit, so einfach. Aber was, wenn die Listbox nicht ALLE Einträge der liste anzeigt, sondern nur die, die ein bestimmtes Kriterium erfüllen? Dann kann ich den Index den mir listbox.curselection()[0] gibt, nicht einfach verwenden.
- Versteht man, was ich meine?
Eine Kopie von liste zu machen in der nur die angezeigten Objekte drinstehen ist auch nicht sinnvoll, denn wenn ich die Einträge der Kopie ändere, ändern sich die Einträge der liste i.A. nicht - aber das sollten sie.
Also bleibt nur, den Index von curselection zu nehmen und dann rumzurechnen, welcher Eintrag von liste dazu wohl gehört hat. Aber dann habe ich gewisse Code-Dopplungen - einmal beim Befüllen der Listbox und dann nochmal beim Rekonstruieren welchen Eintrag der Benutzer wohl gemeint hatte.
Sicherlich bin ich nicht der Erste, der dieses Problem hat. Wie würde das jemand angehen, der Ahnung von der Materie hat? Gibt es dafür irgendwelche Patterns?
Freundliche Grüße
Y.
Re: Listbox, die nicht alles anzeigt
Verfasst: Freitag 8. April 2022, 18:27
von __deets__
Wieso denkst du die Liste wäre teuer? Ist sie nicht. Die Objekte selbst werden dabei ja nicht gedoppelt.
Re: Listbox, die nicht alles anzeigt
Verfasst: Freitag 8. April 2022, 21:26
von Üpsilon
Doch, werden sie. Hier ein Minimalbeispiel, was ich meine:
Code: Alles auswählen
import tkinter as tk
w = tk.Tk()
liste = ["hallo", "quatsch", "mit", "soße", "hussnätter"]
gefilterteliste = [s for s in liste if not s.startswith("h")]
listbox = tk.Listbox()
for s in gefilterteliste:
listbox.insert(tk.END, s)
listbox.pack()
def helau():
if len(listbox.curselection()) != 1:
print("nichts oder zu viel ausgewählt")
return
gefilterteliste[listbox.curselection()[0]] += " HELAU"
print(gefilterteliste)
print(liste)
tk.Button(w, text="helau anhängen", command=helau).pack()
w.mainloop()
Jetzt stelle man sich noch vor, das "h" wäre nicht hartkodiert sondern würde vom Benutzer in einem Entry eingegeben werden. Und die Listbox müsste nach dem Klick auf den Button die geänderten Strings anzeigen.
Re: Listbox, die nicht alles anzeigt
Verfasst: Freitag 8. April 2022, 21:37
von __deets__
Nein, werden sie nicht. So funktioniert python nunmal nicht. Sofern du keinen aufrufe wie copy.deepcopy oder ähnliches nutzt, werden da nur Referenzen auf das gleiche Objekt gespeichert.
Re: Listbox, die nicht alles anzeigt
Verfasst: Freitag 8. April 2022, 21:40
von Üpsilon
__deets__ hat geschrieben: ↑Freitag 8. April 2022, 21:37
Nein, werden sie nicht. So funktioniert python nunmal nicht. Sofern du keinen aufrufe wie copy.deepcopy oder ähnliches nutzt, werden da nur Referenzen auf das gleiche Objekt gespeichert.
Und wieso sehe ich dann in der Ausgabe dass liste sich nicht geändert hat?
Re: Listbox, die nicht alles anzeigt
Verfasst: Freitag 8. April 2022, 21:44
von sparrow
@Üpsilon: Ich sehe auch nicht, wo du ein Objekt in einer Liste veränderst. Ich sehe, dass du `gefilterteliste[listbox.curselection[0]]` etwas _neues_ zuweist.
Hier würdest du auch nicht erwarten, dass der Wert von b plötzlich "ham" wird, oder?
Code: Alles auswählen
>>> a = "spam"
>>> b = a
>>> a = "ham"
>>> print(a)
ham
>>> print(b)
spam
Re: Listbox, die nicht alles anzeigt
Verfasst: Freitag 8. April 2022, 21:54
von Üpsilon
Ich programmiere seit 10 Jahren in dieser Sprache und weiß sehr wohl wie = funktioniert. Ich hatte mich explizit bemüht, meine Ausgangsfrage klar zu formulieren und bedaure, dass mir das nicht hinreichend gelungen ist.
Nochmal: Meine Frage ist - bezogen auf das kleine Beispiel was ich gepostet habe - wie bekommt man es ohne Code-Dopplungen am besten hin, an den ausgewählten Eintrag "HELAU" anzuhängen?
Re: Listbox, die nicht alles anzeigt
Verfasst: Freitag 8. April 2022, 22:02
von Üpsilon
Nevermind ich denke ich habe eine gute Lösung gefunden. Ihr könnt den Faden jetzt zumachen.
Re: Listbox, die nicht alles anzeigt
Verfasst: Freitag 8. April 2022, 22:02
von __deets__
Strings sind nicht deine Objekte. Sondern immutable, und natürlich hast du dann zwei unterschiedliche.
Steckst du hingegen ein dict statt einem String in deine Liste, und änderst das, dann reflektiert sich das auch in beiden Listen. Und das auch schon seit 10 Jahren. Oder mehr.
Re: Listbox, die nicht alles anzeigt
Verfasst: Freitag 8. April 2022, 22:19
von sparrow
Für dem Fall, dass jemand über den Thread stolpert, der noch nicht so viel Erfahrung im Zuweisen hat folgende Session aus dem interaktiven Interpreter. Manchmal sagt das mehr aus als viele Erklärungen.
Code: Alles auswählen
>>> a = "ham"
>>> print(id(a))
2146183766640
>>> l = [a]
>>> x = [l]
>>> print(l)
['ham']
>>> print(x)
[['ham']]
>>> a = "spam"
>>> print(id(a))
2146184025200
>>> print(id(l[0]))
2146183766640
>>> print(l)
['ham']
>>> print(x)
[['ham']]
>>> l[0] = "lemmon"
>>> print(l)
['lemmon']
>>> print(x)
[['lemmon']]
Re: Listbox, die nicht alles anzeigt
Verfasst: Samstag 9. April 2022, 09:42
von __deets__
Um das nochmal klar zu machen (ich war gestern auf dem Mobiltelefon hier unterwegs): dein Ausgangsproblem bezog sich auf die Veraenderung bestehender Objekte, die in zwei Listen - gefiltern und ungefiltert - gefuehrt werden koennen, was dir aber irgendwie nix war. Auf dieses Problem haben sich meine Antworten hier bezogen.
Doch dein Beispiel hier zeigt ein voellig anderes Problem, das *hinzufuegen* eines Objektes an eine eine Liste, mit der Erwartungshaltung, das waere dann auch bei der anderen so. Das ist ein komplett anderes Problem. Niemand hat behauptet, dass da Liste A durch anhaengen an eine andere Liste B implizit mitveraendert wird.
Re: Listbox, die nicht alles anzeigt
Verfasst: Samstag 9. April 2022, 10:17
von sparrow
@__deets__: Ich glaube, er will keinen Eintrag anhängen sondern etwas an die Zeichenkette anhängen. Ersetzt dafür aber das Element der Liste und verändert es nicht.
Re: Listbox, die nicht alles anzeigt
Verfasst: Samstag 9. April 2022, 10:19
von __deets__
Ah, du hast recht. Er modifiziert das Element in-place. Damit ist mein Beitrag zwei hoeher natuerlich Unfug, das entspricht schon dem urspruenglichen Szenario. Aber mutable vs immutable ist natuelich immer noch das Thema.