Liebe Forenmitglieder,
als Neuling möchte ich mich kurz vorstellen. Mein Name ist Heimo, komme aus Graz und bin seit Juli in Pension.
Ich habe in den mittleren 80er Jahren mit dem Programmieren begonnen und hab einiges gemacht. Maschinensprache, Pascal, C++, Basic, Visual Objects, ..... und natürlich diverse Netzwerkgeschichten wie asp, dot net, php etc, Ich mache das gerne und probiere immer wieder was Neues aus. Neuerdings Python. Ein paar Sachen sieht man hier: www.goweb.at
Das bringt mich auch schon zu meinem Anliegen. Ich mache für meinen Schwiegervater eine Markendatenbank (ich weiß, gibt es zu Hauf, aber ich brauch eine Beschäftigung sonst sucht meine Frau eine für mich)
Es geht gut voran, Python ist eine tolle Sache. Aber bei einem Thema hänge ich komplett und probiere schon gefühlte1000 Varianten aus.
Ich denke, ich verstehe das Prinzip dahinter, aber anscheinend täusche ich mich.
Es geht um "dynamic checkboxes". Es funktioniert sehr gut, AUSSER der default Wert. Ich poste mal den Code, vielleicht hat jemand Lust einem Neuling zu helfen.
Ich übergebe einen Array (aMaske) mit dem Text und dem dazugehörigen Wert. Angezeigt wird immer ein leeres Kasterl, ich hab das Gefühl das Programm schreibt immer in alle Kasterl den gleichen /letzten Wert. "einzelmarken_label" ist der Frame auf dem die Boxen gezeigt werden. Es geht an sich vorerst nur mal um den Default Wert, der nicht immer gleich ist.
checkboxes=[]
for i in range(len(aMaske)):
checkbox_var = IntVar(value=aMaske[1])
checkboxes.append(checkbox_var)
checkbox_value = aMaske[0]
checkbox= Checkbutton(einzelmarken_label, text=checkbox_value, variable=checkbox_var, onvalue=1, offvalue=0, command="lambda v=checkbox_value: on_checkbox_change(v, checkbox_var)")
checkbox.pack(side='left', pady=5)
checkbox_var.set(aMaske[1])
Vielen Dank im Voraus.
Beste Grüße
Heimo
neu
Ein vollständiges ausführbares Beispiel, das das Problem zeigt, wäre hilfreich, denn mein Versuch funktioniert einwandfrei:
Eingerückt wird in Python immer mit 4 Leerzeichen pro Ebene, keine Tabs.
Wie Du Checkbutton und IntVar ansprichst, läßt vermuten, dass Du am Anfang `from tkinter import *` stehen hast. *-Importe sind aber schlecht, weil sie unkontrolliert viele Namen in den eigenen Namensraum laden.
Variablenamen werden in Python prinzipiell klein geschrieben und enthalten keine kryptischen Abkürzungen. Was soll das a in aMaske bedeuten? Listen werden üblicherweise im Plural benannt.
Über einen Index iteriert man nicht, weil man über die Liste auch direkt iterieren könnte und gleichzeitig das Tuple entpacken kann.
Du setzt den Wert Deiner IntVar gleich zweimal.
command muß ein Ausführbares Objekt sein, ein String ist falsch. lambda sollte man dafür auch nicht benuzten, es gibt functools.partial um zusätzliche Variablen zu übergeben.
Für jede nicht-triviale GUI braucht es aber eh Klassen, mit der das Übergeben von vielen Variablen entfällt.
Statt das Checkbutton-Event zu überwachen, wäre es besser, sich die Änderungen des IntVars anzuschauen.
Code: Alles auswählen
import tkinter as tk
from functools import partial
def on_intvar_change(name, index, mode, text, variable):
print(text, variable.get())
def main():
atemschutzmasken = [
(0, "keine"),
(1, "einfache Maske"),
(0, "FFP2"),
]
root = tk.Tk()
checkbox_vars = []
for value, text in atemschutzmasken:
variable = tk.IntVar(root, value=value)
checkbox_vars.append(variable)
variable.trace("w", partial(on_intvar_change, text=text, variable=variable))
checkbox = tk.Checkbutton(root, text=text, variable=variable)
checkbox.pack()
root.mainloop()
if __name__ == "__main__":
main()
Wie Du Checkbutton und IntVar ansprichst, läßt vermuten, dass Du am Anfang `from tkinter import *` stehen hast. *-Importe sind aber schlecht, weil sie unkontrolliert viele Namen in den eigenen Namensraum laden.
Variablenamen werden in Python prinzipiell klein geschrieben und enthalten keine kryptischen Abkürzungen. Was soll das a in aMaske bedeuten? Listen werden üblicherweise im Plural benannt.
Über einen Index iteriert man nicht, weil man über die Liste auch direkt iterieren könnte und gleichzeitig das Tuple entpacken kann.
Du setzt den Wert Deiner IntVar gleich zweimal.
command muß ein Ausführbares Objekt sein, ein String ist falsch. lambda sollte man dafür auch nicht benuzten, es gibt functools.partial um zusätzliche Variablen zu übergeben.
Für jede nicht-triviale GUI braucht es aber eh Klassen, mit der das Übergeben von vielen Variablen entfällt.
Statt das Checkbutton-Event zu überwachen, wäre es besser, sich die Änderungen des IntVars anzuschauen.
Guten Morgen,
vielen Dank für die Antwort. Ich werde versuchen, das so umzusetzen.
Du hast recht, ich habe tkinter importiert. Eingerückt mit Tabs (macht das echt einen Unterschied?)
2x gesetzt aus Verzweiflung, hat sich bei den Versuchen ergeben.
command ist nicht nötig, weil ich dann über einen Button (update der DB) auswerte
Über die Behandlung von IntVar habe ich leider nichts aussagekräftiges gefunden, da tappe ich etwas im Dunkeln.
Ich habe gestern aus Versehen einen falschen (alten Versuch) reinkopiert. Hier der richtige.
Ändert aber nichts an Deinen Fakten.
Jetzt sieht das so aus, funktioniert immer noch nicht. checkboxes = create_checkboxes(aMaske) ist das label wo es abgebildet ist
Aufruf :
Array aMaske zb so [['1', 1], ['2', 0], ['3', 1], ['4', 0], ['5', 0]] -> Zahl unter den Anführungszeichen wird angezeigt (passt), Zahl ohne soll der Wert sein. In diesem Fall müsste das 1. und 3. Kasterl gesetzt sein
Array kann auch so sein (also muss string sein) [['(1)',1]] oder [['LV(1)',1]]
Mit besten Grüßen.
Heimo
vielen Dank für die Antwort. Ich werde versuchen, das so umzusetzen.
Du hast recht, ich habe tkinter importiert. Eingerückt mit Tabs (macht das echt einen Unterschied?)
2x gesetzt aus Verzweiflung, hat sich bei den Versuchen ergeben.
command ist nicht nötig, weil ich dann über einen Button (update der DB) auswerte
Über die Behandlung von IntVar habe ich leider nichts aussagekräftiges gefunden, da tappe ich etwas im Dunkeln.
Ich habe gestern aus Versehen einen falschen (alten Versuch) reinkopiert. Hier der richtige.
Code: Alles auswählen
checkboxes=[]
for i in range(len(aMaske)):
checkbox_var = IntVar(value=aMaske[i][1])
checkboxes.append(checkbox_var)
checkbox_value = aMaske[i][0]
checkbox= Checkbutton(einzelmarken_label, text=checkbox_value, variable=checkbox_var, onvalue=1, offvalue=0, command="lambda v=checkbox_value: on_checkbox_change(v, checkbox_var)")
checkbox.pack(side='left', pady=5)
checkbox_var.set(aMaske[i][1])
return checkboxes
Jetzt sieht das so aus, funktioniert immer noch nicht. checkboxes = create_checkboxes(aMaske) ist das label wo es abgebildet ist
Aufruf :
Code: Alles auswählen
checkboxes = create_checkboxes(aMaske)
Array kann auch so sein (also muss string sein) [['(1)',1]] oder [['LV(1)',1]]
Code: Alles auswählen
def create_checkboxes(aMaske):
checkboxes=[]
print(aMaske)
for i in range(len(aMaske)):
checkbox_var = tk.IntVar(einzelmarken_label, value=aMaske[i][1])
checkboxes.append(checkbox_var)
checkbox_value = aMaske[i][0]
checkbox= tk.Checkbutton(einzelmarken_label, text=checkbox_value, variable=checkbox_var, onvalue=1, offvalue=0)
checkbox.pack(side='left', pady=5)
return checkboxes
Heimo
Ich habe das jetzt analog Deinem Beispiel umgesetzt, funktioniert tadellos. Ich hatte das komplett falsch verstanden, dachte get() braucht man nur, wenn man den Inhalt auslesen bzw verwerten will. Schaut jetzt so aus:
Vielen herzlichen Dank und Grüße aus der Steiermark.
Code: Alles auswählen
def on_intvar_change(name, index, mode, text, variable):
print(text, variable.get())
def create_checkbox():
# der Code davor ist nicht relevant
checkbox_vars = []
for value, text in aMaske:
variable = tk.IntVar(einzelmarken_label, value=value)
checkbox_vars.append(variable)
variable.trace("w", partial(on_intvar_change, text=text, variable=variable))
checkbox = tk.Checkbutton(einzelmarken_label, text=text, variable=variable)
checkbox.pack(side='left')