Checkbutton im Menü aktivieren

Fragen zu Tkinter.
Antworten
Benutzeravatar
Mawilo
User
Beiträge: 446
Registriert: Sonntag 22. Februar 2004, 10:58
Wohnort: Sachsen
Kontaktdaten:

Samstag 9. September 2006, 23:26

Hallo,

ich möchte in einem Menü alle Checkbutton beim Erstellen auf "aktiv" setzen. Die Anzahl der Checkbutton ist dabei variabel und wird durch die Einträge in einer Liste bestimmt.

Hier ein Beispielcode:

Code: Alles auswählen

import Tkinter as tk

liste = ['A', 'B', 'C', 'D']

def neueEintraege():
    for i in liste:
        var_b = tk.StringVar()
        var_b.set('on')
        x = mEintrag.add_checkbutton(label = i,
                                variable = var_b,
                                onvalue = 'on',
                                offvalue = 'off')
    
root = tk.Tk()
mBar = tk.Menu(root)
mFile = tk.Menu(mBar)
mEintrag = tk.Menu(mFile)
mFile.add_cascade(label = 'Eintrag 1',
                  menu = mEintrag)
mBar.add_cascade(label = 'Option',
                 menu = mFile)
root["menu"] = mBar

neueEintraege()

root.mainloop()
Wie aktiviere ich alle Checkbutton beim Erstellen? Bei normalen Checkbuttons wird das über select() gemacht. Wie geht das in einem Menü?

Stephan
BlackJack

Sonntag 10. September 2006, 08:13

Du hast es schon fast richtig. Hier scheint wieder durch, dass Python und Tk zwei verschiedene Welten sind. Wenn Du die `StringVar`s nicht irgendwo auf der "Python-Seite" aufhebst, dann werden sie vom Garbage Collector entsorgt.

Code: Alles auswählen

import Tkinter as tk

def main():
    root = tk.Tk()
    main_menu = tk.Menu(root)
    sub_menu = tk.Menu(main_menu)
    main_menu.add_cascade(label='Test', menu=sub_menu)
    variables = list()
    for label in ('A', 'B', 'C'):
        variable = tk.StringVar()
        variable.set('on')
        variables.append(variable)
        sub_menu.add_checkbutton(label=label,
                                 variable=variable,
                                 onvalue='on',
                                 offvalue='off')
    root.config(menu=main_menu)
    
    root.mainloop()

if __name__ == '__main__':
    main()
Benutzeravatar
Mawilo
User
Beiträge: 446
Registriert: Sonntag 22. Februar 2004, 10:58
Wohnort: Sachsen
Kontaktdaten:

Sonntag 10. September 2006, 08:41

Hallo BlackJack,

danke für die schnelle Antwort. Das Beispiel funktioniert wunderbar. Wenn ich das ganze jetzt in mein Programm einbaue, werden die Häckchen leider nicht gesetzt. Die Variablen sind aber alle "on". Ich muss also noch irgendwo anders einen Bug haben.

Hier mal die "Originalfunktion":

Code: Alles auswählen

     def setMenuBases(self):
        self.mOption.entryconfig(0, state = tk.NORMAL)
        variables = list()
        for label in self.bases:
            variable = tk.StringVar()
            variable.set('on')
            variables.append(variable)
            self.mBases.add_checkbutton(label = label,
                                    variable = variable,
                                    onvalue = 'on',
                                    offvalue = 'off')
Wenn ich noch ein

Code: Alles auswählen

for v in variables:
    print v.get()
einbaue, werden mir alle Variablen als "on" ausgegeben.

Gibt es da noch ein paar Stolperfallen, die man beachten muss?

Stephan
Benutzeravatar
Mawilo
User
Beiträge: 446
Registriert: Sonntag 22. Februar 2004, 10:58
Wohnort: Sachsen
Kontaktdaten:

Sonntag 10. September 2006, 08:54

Jetzt habe ich es geschafft. Ich habe die Variablen in self.variables gespeichert und nicht nur in variables :?

Warum macht da Python einen Unterschied? Ich benötige doch die Variablen nur in der Funktion und nicht in der gesamten Klasse?
BlackJack

Sonntag 10. September 2006, 09:16

Wenn die `StringVar`s verschwinden, dann sind sie auch für Tk nicht mehr erreichbar. Wenn Du sie nicht irgendwo dauerhaft speicherst, also mindestens so lange wie das Menü existiert, dann gibt's die beobachteten Probleme.

Warum brauchst Du die denn danach nicht mehr? Da kann man dann doch prima auf die Zustände der Checkbuttons zugreifen.
Benutzeravatar
Mawilo
User
Beiträge: 446
Registriert: Sonntag 22. Februar 2004, 10:58
Wohnort: Sachsen
Kontaktdaten:

Sonntag 10. September 2006, 09:58

Natürlich verwende ich die Liste um den Zustand der Checkbutton abzufragen. Mir war nur im ersten Moment unklar, warum unbedingt das "self" benötigt wird. Jetzt ist mir das schon etwas einleuchtender. Tk findet ja sonst die Variablen nicht, da Tk in einer anderen Funktion der Klasse definiert ist.
Irgendwie habe ich es heute mit den Menüs. Wie kann ich denn das Menü (bzw. nur die Einträge) wieder zerstören? Die beschriebene Funktion kann mehrmals aufgerufen werden. Dabei ändert sich jedesmal die Anzahl der Einträge in der Liste. Jetzt werden die neuen Einträge immer dazugeschrieben. Ein self.mBases.destroy() erzeugt nur eine Fehlermeldung (TclError: invalid command name ".10490384.10492384").


edit: hab's gefunden - self.mBases.delete(0, len(self.bases)) löscht die Menüenträge
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Sonntag 10. September 2006, 11:46

Lösch doch die gesamten Einträge mit

Code: Alles auswählen

self.mBases.delete(0, len(variables))
MfG
HWK
Antworten