Seite 1 von 1
Labels über Listeneintrag konfigurieren
Verfasst: Sonntag 8. September 2019, 13:04
von elofranz
Ich habe eine Liste mit 2 bis 7 Einträgen die sich ständig ändern. Die Einträge werden in einer Listbox angezeigt.
Zur besseren Übersicht möchte ich die Einträge auf Labels aufteilen (um später auch entsprechende Logos anzuzeigen).
Mein Grundgedanke ist die Label in eine Liste einzutragen und in einer Schleife über die Anzahl der Listboxeinträge aufzurufen.
Code: Alles auswählen
from tkinter import *
fenster = Tk()
fenster.geometry("500x500")
lblListe = ["lbl_a","lbl_b","lbl_c","lbl_d","lbl_e","lbl_f","lbl_g"]
wertX = 3 # anzahl
def btn1_click():
print("__________________")
wertLen = len(lblListe)
print("lblListe : ",wertLen)
print("wertX : ",wertX)
print("------------")
counter = 0
while counter < wertX:
print("counter: ", counter)
lblZw = lblListe[counter]
print("lblZw:", lblZw)
print("....")
lblZw.config(font=("ARIAL",18)) ##
counter = counter +1
lbl_a = Label(fenster, text="AAAAAAA")
lbl_a.place(x=20, y=20)
lbl_b = Label(fenster, text="BBBBBBB")
lbl_b.place(x=20, y=50)
lbl3 = Label(fenster, text="CCCCCCC")
lbl3.place(x=20, y=80)
btn1 =Button(fenster,text="click", command= btn1_click)
btn1.place(x=250 , y=300)
fenster.mainloop()
Re: Labels über Listeneintrag konfigurieren
Verfasst: Sonntag 8. September 2019, 16:17
von Sirius3
Gibt es auch eine Frage?
Benutze keine *-Importe, kein place und keine globalen Variablen.
Re: Labels über Listeneintrag konfigurieren
Verfasst: Sonntag 8. September 2019, 17:00
von elofranz

Ja die Frage.
Ich dachte das es möglich ist über die Listeneinträge die Labels aufzurufen.
Wie kann ich die Labels in der Schleife aufrufen.
In meinem Testprogramm erscheint: "AttributeError: 'str' object has no attribute 'config' "
Danke.
Re: Labels über Listeneintrag konfigurieren
Verfasst: Sonntag 8. September 2019, 19:34
von Sirius3
Statt Strings in eine Liste zu packen, kannst Du die Label-Objekte in einer Liste sammeln und benutzen.
Re: Labels über Listeneintrag konfigurieren
Verfasst: Mittwoch 11. September 2019, 20:02
von Populus
Hallo zusammen,
in diese Diskussion steige ich gerne mit ein, da ich mich gerade mit einem ähnlichen Problem rumschlage.
@Sirius3: Wie kann ich mir das vorstellen Label Objekte in einer Liste zu nutzen?
um im Beispiel von elofranz zu bleiben: Ich lege eine Liste von Label Objekten an:
lblListe = [Label(fenster, text="AAAAAAA"), Label(fenster, text="BBBBBB"), Label(fenster, text="CCCCCC")]
Dann funktioniert auch lbl_001 = lblListe[0] problemlos
für mich bleibt noch die Frage wie kann ich die Labels für eine unbekannte Zahl von Labels erstellen?
Kennst du auch einen Trick, wie ich die Variabel lbl_001 usw. automatisch (sagen wir mal in abhängigkeit von einer Dateianzahl x in einem Verzeichnis) generieren kann?
Freue mich auf jede Hilfe - Populus
Re: Labels über Listeneintrag konfigurieren
Verfasst: Mittwoch 11. September 2019, 21:07
von __deets__
Mit einer for-Schleife und dem anhängen an eine Liste.
Re: Labels über Listeneintrag konfigurieren
Verfasst: Freitag 13. September 2019, 08:27
von elofranz
Hallo,
danke für euer Interesse an meinen Problemchen.
Mit dem Code kann ich nun die gewünschte Anzahl von Labels in einen Frame erstellen und ein Bild zuordnen.
Jetzt muss noch das Frame geleert werden, um es mit neuen Daten zu generieren.
Hat jemand eine Idee?
Code: Alles auswählen
from tkinter import *
fenster = Tk()
fenster.geometry("500x500")
bildStart = PhotoImage(file= "StartBild.png")
lblListe = ["lbl_a","lbl_b","lbl_c","lbl_d","lbl_e","lbl_f","lbl_g"]
labels=[] #leere Labelliste
def btn1_click():
print("-----")
for x in lblListe:
zw = x
label = Label(frame1,text=zw, image = bildStart, compound = CENTER )
label.pack()
labels.append(label)
frame1 = Frame(fenster, bg ="SKYBLUE")
frame1.place(x = 10, y =10, width = 150, height =400)
lblText1 = Label(frame1, text="Hallo",image = bildStart)
lblText1.pack()
btn1 =Button(fenster,text="click", command= btn1_click)
btn1.place(x=250 , y=300)
fenster.mainloop()
Re: Labels über Listeneintrag konfigurieren
Verfasst: Freitag 13. September 2019, 09:34
von elofranz

Das sollte funktionieren.
Code: Alles auswählen
from tkinter import *
fenster = Tk()
fenster.geometry("500x500")
# das Bild muss im Ordner vorhanden sein
bildStart = PhotoImage(file= "StartBild.png")
# Liste die vor dem Aufruf der Funktion aktualisiert wird
lblListe = ["wert 1","wert 2","wert 3","wert 100","wert 101","wert Hallo","usw"]
# leere Liste für die LabelNamen
labels=[]
# löscht die erstellte Liste in frame1
# nach Aktualisierung der der lblListe können die Labels neu erstellt werden
def btn2_click():
print("Labels löschen")
for widget in frame1.winfo_children():
widget.destroy()
# Labels in frame1 erstellen
# Text der Labels wir von LblListe übernommen
#
def btn1_click():
print("Labels erstellen")
for x in lblListe:
zw = x
label = Label(frame1,text=zw, image = bildStart, compound = CENTER )
label.pack()
labels.append(label)
frame1 = Frame(fenster, bg ="SKYBLUE")
frame1.place(x = 10, y =10, width = 150, height =400)
lblText1 = Label(frame1, text="Hallo",image = bildStart)
lblText1.pack()
btn1 = Button(fenster,text="click", command= btn1_click)
btn1.place(x=250 , y=300)
btnClear = Button(fenster,text="Clear", command= btn2_click)
btnClear.place(x=250 , y=350)
fenster.mainloop()
Re: Labels über Listeneintrag konfigurieren
Verfasst: Freitag 13. September 2019, 12:09
von Sirius3
Es gilt immer noch: Benutze keine *-Importe, kein place und keine globalen Variablen.
Jetzt ist es sogar noch schlimmer, da Du globale Listen änderst.
Statt die Labels einzeln zu zerstören ist es wesentlich einfacher, alles in einen Frame zu packen und diesen dann zu entfernen.
Variablennamen sollten aussagekräftig sein, keine Abkürzungen enthalten und nicht durchnummeriert werden. Texte in einer Liste an die Variable `lblListe` zu binden ist aus drei Gründen schlecht. Erstens ist lbl eine kryptische Abkürzung, die man sich erst erschließen muß. Der Datentyp sollte nicht im Namen vorkommen, und label_liste ist so nichtssagend, und zudem noch falsch, weil gar keine Labels in dieser Liste sind.
Weiter geht es mit den Texten in dieser Liste, diese werden in einer for-Schleife an die Variable `x` gebunden. Nun gibt es nichts schlechteres als `x` wenn es sich nicht um eine Fließkommazahl handelt, die man in einfachen Rechnungen verwenden will, weil jeder assoziiert das mit einer Zahl. Warum nennst Du dann die Variable in `zw` um, statt gleich `zw` zu benutzen? `zw` ist eine Abkürzung, wo ich beim besten Willen nicht erraten kann, für was das steht.
Dann gibt es noch ein paar handfeste Probleme: Du erzeugst ständig neue Labels, und sammelst alle in einer Liste, ohne diese jemals wieder zu leeren.
Bei GUI-Programmierung kommt man um Klassendefinitionen nicht drumrum.
Re: Labels über Listeneintrag konfigurieren
Verfasst: Freitag 13. September 2019, 12:44
von __blackjack__
Das mag ”funktionieren” ist aber ziemlich schrecklicher Code und löst das Problem auch falsch. Wozu ist denn in diesem Code die `labels`-Liste da? Genau um die geht es doch eigentlich, es wird aber gar nichts sinnvolles damit gemacht.
Aber der Reihe nach: Sternchen-Importe sind Böse™. Man müllt sich damit den Namensraum des aktuellen Moduls unnötig voll.
Auf Modulebene gehört nur Code der Konstanten, Funktionen, und Klassen definiert. Keine Variablen. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.
Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase).
Keine kryptischen Abkürzungen wie `lbl` oder `btn` oder `zw`. Keine nummierten Namen. Und keine Grundatentypen in Namen.
Bei nummerierten Namen will man die Nummer einfach weglassen wenn es sowieso nur eine 1 gibt. Ansonsten will man sich *sinnvolle* Namen ausdenken oder gar keine Einzelnamen sondern eine Datenstruktur. Oft eine Liste. Bei `btn1_click()` und `btn2_click()` sind die Namen besch…eiden und man möchte dort sinnvolle Namen verwenden die beschreiben was die Funktionen machen. Oder, weil es Rückruffunktionen sind, Namen die Beschreiben bei welchem Ereignis die Funktion ausgeführt werden soll.
Es ist ja eine Sache sich was Leerzeichensetzung angeht nicht an den
Style Guide for Python Code zu halten, aber offenbar einen Würfel zu benutzen um an jeder einzelnen Stelle zu entscheiden ob man ein Leerzeichen setzt oder nicht ist extrem.
Die Fenstergrösse gibt man nur vor wenn die GUI mindestens ein Element enthält das sich in der Grösse verändert wenn der Benutzer manuell die Fenstergrösse verändert. Ansonsten ergibt sich die Fenstergrösse automatisch durch den Inhalt des Fensters. Ausser man vewendet `place()` – was man aber nicht tut. Unter anderem weil sonst die Fenstergrösse nicht automatisch ermittelt werden kann.
Daraus das Variablen nicht auf Modulebene gehören, resultiert das Funktionen und Methoden alles was sie ausser Konstanten benötigen als Argument(e) übergeben bekommen. An der Stelle braucht man in GUIs mindestens ``lambda``-Ausdrücke oder `functools.partial()` oder objektorientierte Programmierung (OOP). OOP braucht man für jede nicht-triviale GUI.
`x` ist ein schlechter Name für eine Zeichenkette in einer Schleife und den dan nur zu verwenden um die Zeichenkette an einen anderen furchtbar schlechten Namen (`zw`) zu binden ist ziemlich sinnfrei.
Code: Alles auswählen
#!/usr/bin/env python3
from functools import partial
import tkinter as tk
def create_labels(image, frame, labels, texts):
print("Labels erstellen")
for text in texts:
label = tk.Label(frame, text=text, image=image, compound=tk.CENTER)
label.pack()
labels.append(label)
def destroy_labels(labels):
print("Labels löschen")
for label in labels:
label.destroy()
labels.clear()
def main():
fenster = tk.Tk()
image = tk.PhotoImage(file="StartBild.png")
label_texts = [
"wert 1",
"wert 2",
"wert 3",
"wert 100",
"wert 101",
"wert Hallo",
"usw",
]
frame = tk.Frame(fenster, bg="skyblue")
frame.pack(side=tk.LEFT)
label = tk.Label(frame, text="Hallo", image=image)
label.pack()
labels = [label]
button_frame = tk.Frame(fenster)
button_frame.pack(side=tk.LEFT, anchor=tk.S)
tk.Button(
button_frame,
text="Create",
command=partial(create_labels, image, frame, labels, label_texts),
).pack()
tk.Button(
button_frame, text="Clear", command=partial(destroy_labels, labels)
).pack()
fenster.mainloop()
if __name__ == "__main__":
main()
Re: Labels über Listeneintrag konfigurieren
Verfasst: Donnerstag 19. September 2019, 15:19
von elofranz
Danke, das hat mir weitergeholfen.
Ich habe noch eine Frage zu den erzeugten Labels.
Kann man die werte einzelner Labels noch ändern?
Und wie müsste man die Objekte ansprechen?

Re: Labels über Listeneintrag konfigurieren
Verfasst: Donnerstag 19. September 2019, 15:52
von __blackjack__
@elofranz: Klar, die Werte kann man ändern. Die stecken ja in der `labels`-Liste in der `main()`-Funktion und kann von dort falls benötigt auch an andere Funktionen übergeben werden. Wie das bei `destroy_labels()` passiert. Statt die `destroy()`-Methode aufzurufen könnte man natürlich auch den Text oder andere Optionen von den `Label`-Objekten ändern.
Code: Alles auswählen
#!/usr/bin/env python3
from functools import partial
import tkinter as tk
def create_labels(image, frame, labels, texts):
print("Labels erstellen")
for text in texts:
label = tk.Label(frame, text=text, image=image, compound=tk.CENTER)
label.pack()
labels.append(label)
def extend_labels(labels):
for label in labels:
label["text"] = label["text"] + "!"
def destroy_labels(labels):
print("Labels löschen")
for label in labels:
label.destroy()
labels.clear()
def main():
fenster = tk.Tk()
image = tk.PhotoImage(file="StartBild.png")
label_texts = [
"wert 1",
"wert 2",
"wert 3",
"wert 100",
"wert 101",
"wert Hallo",
"usw",
]
frame = tk.Frame(fenster, bg="skyblue")
frame.pack(side=tk.LEFT)
label = tk.Label(frame, text="Hallo", image=image)
label.pack()
labels = [label]
button_frame = tk.Frame(fenster)
button_frame.pack(side=tk.LEFT, anchor=tk.S)
tk.Button(
button_frame,
text="Create",
command=partial(create_labels, image, frame, labels, label_texts),
).pack()
tk.Button(
button_frame, text="Extend", command=partial(extend_labels, labels)
).pack()
tk.Button(
button_frame, text="Clear", command=partial(destroy_labels, labels)
).pack()
fenster.mainloop()
if __name__ == "__main__":
main()
Re: Labels über Listeneintrag konfigurieren
Verfasst: Donnerstag 19. September 2019, 18:14
von elofranz
Danke für die schnellen Antworten !!
Also um neue werte zuzuweisen Labels löschen Liste überarbeiten und Labels neu anlegen.
Ach der Böse import*.
Eine Anfängerfrage, woher weiss man was man aus dem Modul braucht und was nicht.
Re: Labels über Listeneintrag konfigurieren
Verfasst: Donnerstag 19. September 2019, 18:56
von __blackjack__
@elofranz: Die Frage verstehe ich nicht so ganz — Du weisst doch, egal ob Anfänger oder nicht, was Du brauchst wenn Du es brauchst. Ist ja nicht so das man alles beim ``import`` hinschreiben muss bevor man anfangen darf den Rest zu programmieren und das man nichts mehr an den ``import``-Anweisungen ändern darf wenn man mal angefangen hat den Teil nach den Importen zu schreiben.
Re: Labels über Listeneintrag konfigurieren
Verfasst: Samstag 21. September 2019, 14:57
von Nummer_42O
__blackjack__ hat geschrieben: Donnerstag 19. September 2019, 18:56
@elofranz: Die Frage verstehe ich nicht so ganz — Du weisst doch, egal ob Anfänger oder nicht, was Du brauchst wenn Du es brauchst. Ist ja nicht so das man alles beim ``import`` hinschreiben muss bevor man anfangen darf den Rest zu programmieren und das man nichts mehr an den ``import``-Anweisungen ändern darf wenn man mal angefangen hat den Teil nach den Importen zu schreiben.
Und was genau ist das Problem an
? Schmiert dann bei euch Python ab, oder wie?
Re: Labels über Listeneintrag konfigurieren
Verfasst: Samstag 21. September 2019, 15:47
von __deets__
Hat BlackJack oben beschrieben.