neu

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Heimo
User
Beiträge: 3
Registriert: Donnerstag 9. Januar 2025, 18:20

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
Sirius3
User
Beiträge: 18115
Registriert: Sonntag 21. Oktober 2012, 17:20

Ein vollständiges ausführbares Beispiel, das das Problem zeigt, wäre hilfreich, denn mein Versuch funktioniert einwandfrei:

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()
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.
Heimo
User
Beiträge: 3
Registriert: Donnerstag 9. Januar 2025, 18:20

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.

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
Ä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 :

Code: Alles auswählen

checkboxes = create_checkboxes(aMaske)
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]]

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
Mit besten Grüßen.

Heimo
Sirius3
User
Beiträge: 18115
Registriert: Sonntag 21. Oktober 2012, 17:20

Ich sehe jetzt keinen Unterschied. Wie sieht ein komplettes ausführbares Beispiel aus, das den Fehler zeigt?
Heimo
User
Beiträge: 3
Registriert: Donnerstag 9. Januar 2025, 18:20

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:

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')

Vielen herzlichen Dank und Grüße aus der Steiermark.
Antworten