Checkboxen mit aus Schleife ausblenden

Fragen zu Tkinter.
Antworten
Bastian
User
Beiträge: 3
Registriert: Mittwoch 15. Mai 2019, 14:05

Hallo in die Runde,
ich befasse mich seit einiger Zeit mit Python, habe aber erst vor kurzem angefangen einige Dinge mit Tkinter zu testen. Dabei bin ich auf ein Problem gestoßen, dass ich auch durch Google/Forum nicht lösen konnte, evtl kann mir hier ja jemand helfen:

Was ich erstellen möchte ist ein Fenster mit so vielen Checkboxen, wie ich Namen in einer Liste habe.
--> geht mit einer for schleife und mit tk.Variable() kann ich auch auslesen, welches Element aktiviert ist.
Jetzt möchte ich einzelne Checkboxen ausblenden. Also ich drücke auf einen Knopf worauf dann alle ausgewählten checkboxen ausgeblendet werden. mit .pack_forget() kann ich leider nur die letzte Checkbox ausblenden.

Ich würede mich sehr freuen wenn mir jemand sagen könnte wie ich dies bewerkstelligen kann.

Danke und beste Grüße

Basti

Code: Alles auswählen

import tkinter as tk
liste = ["a","b","c","d","e"]
enable ={}

def ende():
    main.destroy()


def forget():
    cb.pack_forget()


def button2():
    cb.pack()

# Hauptfenster
main = tk.Tk()


b_ende = tk.Button(main, text="Ende", command=ende)
b_ende.pack()
b = tk.Button(main, text="eintrag2", command=forget)
b.pack()
b2 = tk.Button(main, text="eintrag2", command=button2)
b2.pack()


for element in liste:
    print (liste)
    print(element)
    enable[element] = tk.Variable()
    cb = tk.Checkbutton(main, text=element , variable=enable[element])
    enable[element].set(0)
    cb.pack()


main.mainloop()
Benutzeravatar
sparrow
User
Beiträge: 4186
Registriert: Freitag 17. April 2009, 10:28

So etwas gehört in Klassen struktuiert.

Wenn du die Buttons in eine Liste packst, hast du hinterher auch mehr als den letzten verfügbar. Bisher bindest du ja immer den aktuellen, beim Erstellen an den Namen "cb".
Bastian
User
Beiträge: 3
Registriert: Mittwoch 15. Mai 2019, 14:05

Danke für den Tipp, ich werde das mal probieren
Benutzeravatar
__blackjack__
User
Beiträge: 13071
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Bastian: Der Name `main()` ist normalerweise schon der Name der Hauptfunktion. Das Hauptfenster heisst bei Tk traditionell `root`.

Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Alles was Funktionen und Methoden ausser Konstanten benötigen sollte als Argument(e) übergeben werden. Für Rückrufe bei Tk braucht man deshalb entweder Closures (`functools.partial()` oder ``lambda``-Ausdrücke), oder eben Klassen.

Keines der `Button`-Objekte wird nach dem anordnen auf der GUI noch benötigt, da braucht man also auch keine schlechten Namen vergeben.

Für das `ende()` brauchst Du keine Funktion. Da wird ja sowieso nur eine Methode drin aufgerufen, da kannst Du auch gleich diese Methode als `command` übergeben. Ich würde da auch eher `quit()` statt `destroy()` nehmen.

`tk.Variable` wird eher nicht verwendet. Das ist die Basisklasse. Wenn man nichts an `onvalue`/`offvalue` vom `Checkbutton` ändert, dann will man eine `tk.IntVar` verwenden.

Man kann den Wert auch gleich beim erstellen setzen. Wobei 0 die Voreinstellung (`offvalue`) ist, das braucht man also gar nicht explizit machen.

Code: Alles auswählen

#!/usr/bin/env python3
import tkinter as tk
from collections import namedtuple
from functools import partial

Checkbox = namedtuple('Checkbox', 'check_button variable')


def forget_selected(checkboxes):
    for checkbox in checkboxes:
        if checkbox.variable.get():
            checkbox.check_button.pack_forget()


def main():
    root = tk.Tk()

    tk.Button(root, text='Ende', command=root.quit).pack()
    remove_button = tk.Button(root, text='Entfernen')
    remove_button.pack()

    checkboxes = list()
    for character in ['a', 'b', 'c', 'd', 'e']:
        variable = tk.IntVar()
        check_button = tk.Checkbutton(root, text=character, variable=variable)
        check_button.pack()
        checkboxes.append(Checkbox(check_button, variable))

    remove_button['command'] = partial(forget_selected, checkboxes)

    root.mainloop()


if __name__ == '__main__':
    main()
Was Du mit dem zweiten Button machen wolltest war mir nicht klar, darum habe ich den weggelassen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Bastian
User
Beiträge: 3
Registriert: Mittwoch 15. Mai 2019, 14:05

Danke _backjack_ für die Tipps und den Code.
der funktioniert genau so wie ich es mir vorgestellt habe, jetzt muss ich nur noch genau verstehen warum, habe aber dank dir etwas woran ich mich orientieren kann.
Antworten