Checkbutton select mit Liste

Fragen zu Tkinter.
Antworten
Sirius3
User
Beiträge: 18264
Registriert: Sonntag 21. Oktober 2012, 17:20

@Philipp68: da ist so einiges schief. Dateien, die man öffnet, sollte man auch wieder schließen (am besten mit with-Statement). fobj ist kein File-Objekt, wie der Name vermuten läßt, sondern ein String. Die for-Schleife geht dann über die Zeichen der Zeile, Du speicherst aber anscheinend die Zahlen als Python-Liste (das sollte am besten JSON sein und mit Hilfe des entsprechenden Modul geschrieben und gelesen werden). `line` verwendest Du aber gar nicht, sondern nur `fobj` das zzz selektiert, wenn irgendwo eine 1 in dieser Zeile vorkommt. Dann steht in `zzz` nur die letzte Checkbox, Du mußt Dir also alle Checkboxen beim Erzeugen merken (am besten in einer Liste).
Sirius3
User
Beiträge: 18264
Registriert: Sonntag 21. Oktober 2012, 17:20

@Philipp68: dann sind die vielen Beispiele alle schlecht. In Python werden selten Indexzugriffe benutzt. Schau mal, wo Du überall `listcheck` setzt.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Die Namen die du da siehst sind interne Namen von tkinter. Der nummeriert halt irgendwas durch. Was hat das mit dir zu tun? Du musst doch nur mit dem entsprechenden Index auf die entsprechende Checkbox zugreifen.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Weil ich gerade mal Lust hatte zu zeigen, wie man sowas eigentlich macht habe ich mal dieses kleine Testprogramm geschrieben.

Tkinter ist zwar nicht das gelbe vom Ei, aber etwas das es gut macht und das man verwenden sollte sind die Var-Klassen. Damit kann man sauber Daten von GUI trennen, und sich reziprok von Aenderungen benachrichtigen lassen. Und bei Checkboxen insbesondere ist das auch das vorgeschlagene Vorgehen.

Code: Alles auswählen

import math
import tkinter as tk
import json
import tempfile
from functools import partial
from itertools import cycle


TEST_DATA = [
    [
        1, 1, 0, 1,
        0, 1, 0, 1,
        1, 1, 0, 1,
        0, 1, 0, 1,
        1, 1, 0, 1,
        0, 1, 0, 1
    ],
    [
        1, 0, 1, 1,
        0, 1, 0, 1,
        1, 0, 1, 1,
        0, 1, 0, 1,
        0, 0, 1, 1,
        0, 1, 1, 0
    ],
]


class CircleView(object):

    def __init__(self, parent, model, width=400, height=400):
        frame = tk.Frame(parent)
        frame.config(width=width, height=height)
        frame.pack()

        for i, var in enumerate(model):
            step = math.pi * 2 / len(model) * i
            x = math.cos(step) * (width / 2) * .8 + width / 2
            y = math.sin(step) * (width / 2) * .8 + width / 2
            cb = tk.Checkbutton(frame, var=var)
            cb.place(x=x, y=y)


class CircleModel(object):

    def __init__(self):
        self._vars = [tk.IntVar() for _ in range(24)]


    def __iter__(self):
        return iter(self._vars)


    def __len__(self):
        return len(self._vars)


    def load(self, path):
        with open(path) as inf:
            data = json.load(inf)
            for var, value in zip(self._vars, data):
                var.set(value)


    def save(self, path):
        with open(path, "w") as outf:
            json.dump([var.get() for var in self._vars], outf)


def write_test_data():
    res = []
    for data in TEST_DATA:
        f = tempfile.mktemp()
        with open(f, "w") as outf:
            json.dump(data, outf)
        res.append(f)
    return res


def swap_test_data(filenames, model, root):
    model.load(next(filenames))

    f = partial(swap_test_data, filenames, model, root)
    root.after(2000, lambda: f())


def main():
    test_data_files = write_test_data()
    root = tk.Tk()
    model = CircleModel()
    v = CircleView(root, model)

    f = partial(swap_test_data, cycle(test_data_files), model, root)
    root.after(2000, lambda: f())

    b = tk.Button(root, text="Save", command=lambda: model.save("/tmp/test.json"))
    b.pack()
    tk.mainloop()

if __name__ == '__main__':
    main()
Antworten