Checkbutton Frage/Problem - Anregung gesucht

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

@Kalli87: ich meinte, dass label_data zu viel redundante Daten enthält

Code: Alles auswählen

           self.cursor.execute("select bilder.studie_nr, bilder.serie_nr, bilder.image_nr "
               "from bilder, patient where patient.patnu=bilder.patnu "
               "and patient.patnu=%s", [self.eingabe.get()])
            for row, (studie, serie, image) in enumerate(self.cursor, 1):
                self.test_checkbox = StringVar()
 
                label_data = [
                    (row, 'lightblue'),
                    (self.datum_ausgabe, ''),
                    (image, ''),
                    (serie, ''),
                    (studie, ''),
                ]
                for column, (text, background) in enumerate(label_data):
                    Label(self.ueberframe, text=text, relief='sunken',
                          anchor=CENTER, background=background).grid(
                          row=row, column=column, sticky=NSEW)
                Checkbutton(self.ueberframe, variable=self.test_checkbox,
                    onvalue="Serie: {} Studie: {}".format(serie,studie),
                    offvalue="", command=self.liste_checkbutton).grid(row=row, column=5)
Und jetzt schau mal, welche Variable bei jedem Schleifendurchgang überschrieben wird.
Kalli87
User
Beiträge: 281
Registriert: Montag 10. November 2014, 11:27

@Sirius3: Wenn ich´s richtig gesehen hab, und ich denke mal ich liege richtig, dann wird immer "self.test_checkbox = StringVar()" überschrieben.

Edit: Jedenfalls wo ich mir deinen Code angeschaut hab kam es mir so vor als wäre das die Stelle.
Kalli87
User
Beiträge: 281
Registriert: Montag 10. November 2014, 11:27

Ich versteh leider immer noch nicht wo der Fehler liegt, welche Variable wird denn nun immer überschrieben?
Sirius3
User
Beiträge: 18259
Registriert: Sonntag 21. Oktober 2012, 17:20

@Kalli87: Du hast es schon richtig erkannt, das Problem ist "self.test_checkbox = StringVar()".
Kalli87
User
Beiträge: 281
Registriert: Montag 10. November 2014, 11:27

@Sirius3: Also lag ich in der Hinsicht schon richtig. Muss ich also nur gucken wo "self.test_checkbox = StringVar()" stehen muss damit das anklicken richtig funktioniert und auch die Datensätze stimmen. Beides wollte bis jetzt ja nicht so richtig.
Sirius3
User
Beiträge: 18259
Registriert: Sonntag 21. Oktober 2012, 17:20

@Kalli87: die Position ist schon die richtige. Aber die StringVars müssen halt in eine Liste.
Kalli87
User
Beiträge: 281
Registriert: Montag 10. November 2014, 11:27

@Sirius3: Also würde es ja an sich reichen wenn ich eine leere Liste anlege und die StringVars mit append anhänge?
Sprich: self.checkbox.append(StringVar()) ?

Sorry das ich jetzt erst wieder etwas dazu schreibe aber ich wurde kurzzeitig von einer anderen Sache Inanspruch genommen.
Danke
Sirius3
User
Beiträge: 18259
Registriert: Sonntag 21. Oktober 2012, 17:20

@Kalli87: Du kannst hier ja nicht immer jeden Kleinkram fragen. Selbst überlegen, ob und warum das Sinn machen würde, ausprobieren, testen, modifizieren, wieder testen, bis es gut ist.
Kalli87
User
Beiträge: 281
Registriert: Montag 10. November 2014, 11:27

Nach vielen probieren und lesen hab ich, vermute es jedenfalls, geschafft es in die richtige Richtung zu führen.
Soll heißen, ich hab die StringVar bzw jetzt IntVar da es sich ja um reine Zahlen handelt in eine liste gehangen/geschrieben.
Wenn ich das ganze aber jetzt ausgeben will kommt das " <generator object <genexpr> at 0x2d0bd70> "
Ich hab dann meine Bücher gewälzt und bin auf Generatorausdrücke/Generatorfunktionen gestoßen wo genau das beschrieben wird. Laut Buch kann man nur eine vernünftige Ausgabe bekommen wenn man das ganze in eine "For-Schleife" packt, gesagt getan und ausprobiert. Nur das Problem ist jetzt das die Ausgabe leer bleibt.

Hier der Code für die Checkboxen

Code: Alles auswählen

            self.checkbox = []
            for row,(self.studie, self.serie, image) in enumerate(self.cursor, 1):
                self.checkbox.append(IntVar())

                self.label_data = \
                [
                    (row, 'lightblue'),
                    (self.datum_ausgabe, ''),
                    (image, ''),
                    (self.serie, ''),
                    (self.studie, ''),
                ]
                for column, (text, background) in enumerate(self.label_data):
                    Label(self.ueberframe, text=text, relief='sunken', anchor=CENTER, background=background).grid(row=row, column=column, sticky=NSEW)
                Checkbutton(self.ueberframe, variable=self.checkbox,onvalue="Serie: {} Studie: {}".format(self.serie,self.studie),command=self.list_checkbox,offvalue="", ).grid(row=row, column=5)


            if self.ges == 1:
                self.ges = "M"      #Männlich
            else:
                self.ges = "W"      #Weiblich
            self.ausgabe_ges.insert("end", self.ges)
Hier der Code zum testen ob etwas in der Liste der Checkbox steht

Code: Alles auswählen

    def list_checkbox(self):
        checklist = (check.get() for check in self.checkbox if check.get())
        print(checklist)
        for n in checklist:
            print(n, end=" ")
Ich hab das Internet ebenso durchforstet wenn ich direkt die Checklist mit print() ausgebe kommt die Ausgabe die ich oben beschrieben habe.
Lass ich das durch die for-schleife laufen kommt gar keine Ausgabe oder bleibt einfach leer
BlackJack

Kalli87: Wenn da keine Ausgabe kommt dann gibt es offenbar keine Elemente in `self.checkbox` bei denen die `get()`-Methode einen Wert liefert der im Boole'schen-Kontext beim ``if`` ”wahr” ist.

Wenn Du erst nachlesen musst was ein Generatorausdruck ist, wie kommst Du denn dann dazu einen zu schreiben? Wenn Du dort eine Liste haben möchtest, warum schreibst Du dann einen Generatorausdruck und keine „list comprehension” (LC). Oder halt eine Schleife wie man sie schreiben würde wenn man weder Generatorausdruck noch LC kennt‽

`self.checkbox` ist ein schlechter Name für einen Containerdatentyp, der zudem noch nicht einmal Checkboxen enthält. Was bedeuten denn die Werte hinter diesem Attribut im Programm? Danach sollte der Name gewählt werden.

Warum heisst `self.ges` nicht `self.geschlecht`, damit man nicht raten muss was diese kryptische Abkürzung wohl bedeuten mag‽ Und das dieses Attribut zu verschiedenen Zeiten entweder an eine Zahl oder an Buchstaben gebunden ist, ist keine gute Idee. Ein Name sollte in der Regel nur an Werte von einem (Duck-)Typ gebunden werden, und nicht mal an 1 und mal an 'M' wobei beides im Grunde auch noch die gleiche Bedeutung hat. Das ist verwirrend.

Du bindest auch immer noch alles mögliche an das Objekt was da ganz sicher nicht hingehört.

Ebenfalls falsch ist der Wert vom `variable`-Argument beim erstellen der `Checkbox`-Objekte. Da muss ein `StringVar`-Objekt übergeben werden. Und ganz sicher keine Liste. Was erwartest Du denn was *das* bedeuten sollte‽ Ich habe das Gefühl Du hast nicht verstanden was Du da machst und das Du Dich so durch rätst. So funktioniert programmieren nicht.
Kalli87
User
Beiträge: 281
Registriert: Montag 10. November 2014, 11:27

@BlackJack:
Wenn Du erst nachlesen musst was ein Generatorausdruck ist, wie kommst Du denn dann dazu einen zu schreiben? Wenn Du dort eine Liste haben möchtest, warum schreibst Du dann einen Generatorausdruck und keine „list comprehension” (LC). Oder halt eine Schleife wie man sie schreiben würde wenn man weder Generatorausdruck noch LC kennt‽
Laut Sirius3 sollte ich StringVar am besten in eine liste packen darauf is das ganze ja erst entstanden.
Hab ja auch in meinem vorherigem post auch geschrieben das ich " <generator object <genexpr> at 0x2d0bd70> " bekommen habe und deswegen danach gesucht habe.

Hätte das Stückchen Code mit dem Geschlecht nicht dummerweise geposted hätte es keine gesehen, hab es aber abgändert.......

Was binde ich denn immer noch zuviel an das Objekt?

Wie sagt man so schön? Probieren geht über studieren, klar probier ich rum da ich keine Ahnung habe wo nun das Problem genau liegt. Ich finde auch nix im Internet was ähnlich vom Problem her aufgebaut is und meine Bücher sind da braucht man gar nicht drüber reden.
Sirius3
User
Beiträge: 18259
Registriert: Sonntag 21. Oktober 2012, 17:20

@Kalli87: Wenn Du es nicht selbst herausfinden willst, warum sind "self.studie", "self.serie" oder "self.label_data" ans Objekt gebunden?
Dass Du die StringVars in eine Liste packen sollst ist doch gar nicht falsch, Du hast aber scheinbar immer noch nicht verstanden warum, sonst würdest Du nicht immer wieder fragen. Das Problem ist ja, dass Variablen mit falschen Typen an Funktionen übergeben werden, die dann irgendetwas seltsames damit anstellen, was nicht zu dem gewünschten Ergebnis führt. Tk ist in dieser Hinsicht sehr großzügig, was die Fehlersuche nicht unbedingt einfacher macht.
Kalli87
User
Beiträge: 281
Registriert: Montag 10. November 2014, 11:27

@Sirius3: Mal ganz langsam bitte, wie kommst du drauf das "self.label_data" ein der Checkbox hängt? da steht doch nur in der "onvalue" self.serie und self.studie und wird auch nicht irgendwie in der Checkbox verwendet. Oder reden wir hier nicht mehr von der Checkbox :shock: ?????

Wenn ich das ganze nicht in die Liste packe wird doch immer nur der letzte wert der Checkbox übertragen, der erste wird dann immer überschrieben oder geht verloren oder wie auch immer, jedenfalls ist er nicht da. Soweit waren wir doch schon....
Das mit der Liste hatte das Problem gelöst, nur das jetzt dieses komische "generator" gedönse auftaucht und mir neue Probleme bereitet nervt einfach.
Ich bekomm ja nicht mal Fehlermeldungen, nur Ausgaben die nichts aussagen.

Ich hab extra eine Funktion noch geschrieben die mir das ganze in eine Datei schreibt was genau übertragen wird und da wird nur der ausgewählte Radio-Button richtig übertragen ansonsten kommt irgendwelche grütze die meilen weit davon entfernt ist was eigentlich dort hätte stehen müssen. (Von den Checkboxen her))
BlackJack

@Kalli87: `self.label_data` wird ganz offensichtlich auf `self` als Attribut gesetzt. Warum? Und nein das hat nichts mit der `Checkbox` zu tun.

Dieses „"generator" gedönse” taucht ja nicht einfach so aus dem nichts auf, das hast *Du* ja in das Programm eingebaut. Schreib keinen Generatorausdruck wenn Du keinen Generatorausdruck haben möchtest. :K
Sirius3
User
Beiträge: 18259
Registriert: Sonntag 21. Oktober 2012, 17:20

@Kalli87: Du hast scheinbar so wenig von Deinem eigenen Programm verstanden, dass Du nicht merkst, dass BlackJack oder ich von ganz unterschiedlichen Dingen reden. Programmieren heißt immer, dass man ein komplexes Problem in einfachere Teile zerlegt, diese löst und dann das ganze zu komplizierteren Konstrukten zusammensetzt. Wenn Du das einfache Problem (eine Checkbox) gelöst hast, mußt Du nun das komplexere Problem (viele Checkboxen) lösen, indem Du die Standardlösung eins -> viele anwendest, die bei allen ähnlichen Problemen anwendbar ist: Listen.
Ich würde Dir empfehlen, weg von den Checkboxen, hin zu einem simplen Problem zu gehen, an dem Du das Problem eins -> viele üben kannst. So wie jetzt kommen wir glaube ich nicht weiter. Beispiel: eine Zahl verdoppeln, viele Zahlen verdoppeln.

Ich habe nie gesagt, dass "self.label_data" an irgendwelchen Checkboxen hängen, sondern gefragt warum label_data an self hängt?
Kalli87
User
Beiträge: 281
Registriert: Montag 10. November 2014, 11:27

So ich hoffe ihr habt Ostern gut überstanden ;)
Ich hab die freien Tage genutzt um mal abzuschalten und hab mir heute den Code mal angeschaut und hab es nun so gelöst.

Code: Alles auswählen

            self.cursor.execute("select bilder.studie_nr, bilder.serie_nr, bilder.image_nr from bilder, patient where patient.patnu=bilder.patnu and patient.patnu=%s", [self.eingabe.get()])
            self.checkbox=[]
            for row,(studie, serie, image) in enumerate(self.cursor, 1):
                label_data = \
                [
                    (row, 'lightblue'),
                    (self.datum_ausgabe, ''),
                    (image, ''),
                    (serie, ''),
                    (studie, ''),
                ]
                self.liste=('Serie: {} Studie: {}'.format(str(serie),str(studie)))
                self.checkbox.append(self.liste)

                for column, (text, background) in enumerate(label_data):
                    Label(self.ueberframe, text=text, relief='sunken', anchor=CENTER, background=background).grid(row=row, column=column, sticky=NSEW)
                Checkbutton(self.ueberframe,text=self.liste ,variable=self.checkbox, onvalue=self.liste,command=self.list_checkbox,offvalue="", ).grid(row=row, column=5)
Jetzt haut auch die Ausgabe mit "print" hin und bei "text" wird es auch richtig ausgegeben.
BlackJack

@Kalli87: Da wird immer noch zu viel an das Objekt gebunden und mindestens zwei Namen sind total falsch und irreführend.
Kalli87
User
Beiträge: 281
Registriert: Montag 10. November 2014, 11:27

@BlackJack: Du schaffst es auch immer wieder meine kleinen Erfolgserlebnisse kaputt zu machen :P
Ps.: Bissl Spaß muss auch mal sein ;)
Sirius3
User
Beiträge: 18259
Registriert: Sonntag 21. Oktober 2012, 17:20

@Kalli87: Du hast immer noch die irrsinnige Zuweisung der Checkbox-Liste an das variable-Argument. Was glaubst Du soll das bewirken? self.liste ist neben der Tatsache, das das kein Attribut sein sollte, zudem noch ein schlechter Variablenname. Die str-Aufrufe im format sind überflüssig. Für was brauchst Du die checkbox-Liste jetzt überhaupt noch?
Kalli87
User
Beiträge: 281
Registriert: Montag 10. November 2014, 11:27

@Sirius3: Das meine Checkbox extrem zugemüllt ist mir bewusst. Das mit dem str-Aufruf hab ich behoben. self.liste heißt nicht mehr self.liste und der code sieht mittlerweile auch bissl anders aus aber auch nur minimal.
Was ich jetzt noch brauche oder machen will bzw. lösen muss ist das jede Checkbox ihren eigenen Wert hat also von studie und serie, aber bis jetzt is es eher so das jede checkbox alle werte hat von studie und serie wenn ich diese aktiviere was natürlich müll is.

Ps.: Mal eine Frage am rand, warum wird mein Code eigentlich immer so hart auseinandergenommen und so kritisiert? Ich weiß ja selbst das der wirklich nicht schön und auch an gewissen stellen mehr als überflüssig is.
Antworten