Auslesen Radio-Variable als dictionary schlägt fehl

Fragen zu Tkinter.
Antworten
egerlach
User
Beiträge: 41
Registriert: Samstag 14. März 2009, 21:32

Hallo,
ein Radiobutton wird korrekt ausgelesen:

Code: Alles auswählen

print pWahl.get()
Ergebnis des 'print':
{'nummer': '1', 'nachname': 'Müller', 'vorname': 'Fritz', 'gebdat': '15.01.1985'}

Nur leider kann ich dann NICHT mehr assoziativ (dictionary) auf die Felder zugreifen, ein

Code: Alles auswählen

x=pWahl.get()
print x["nummer"]
resultiert in:
TypeError: string indices must be integers

"must be integers" - befohlen, getan: ein print x[3] gibt dann dritte Zeichen von {'nummer.... aus, also das "u" von "nummer"! Mit dem get() für das Auslesen der Variablen wird der Datentyp also nicht mehr erkannt, sondern ein Zeichen-String gelesen. Was mache ich falsch? - Kann hinter das get() noch irgendwas in die Klammer geschrieben werden ;-) ?

Eine assoziativer Liste wird in python wohl eher mit dictionary bezeichnet

danke schonmal
Eckard
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Ein Radiobutton hat gar keine get()-Methode.

Und die Widgets, die eine get()-Methode haben, liefern Zeichenketten zurück und kein dictionary. Und das ist hier auch so. Das, was wie ein dictionary aussieht, ist in Wahrheit eine Zeichenkette. Dein Beispiel mit x[3] zeigt das auch: Das "u" ist nämlich das Zeichen an der 3. Stelle von "{'nummer': ...." und nicht das 3. Zeichen von "nummer" ...
egerlach hat geschrieben:Eine assoziativer Liste wird in python wohl eher mit dictionary bezeichnet
Ja.
egerlach
User
Beiträge: 41
Registriert: Samstag 14. März 2009, 21:32

numerix hat geschrieben:Ein Radiobutton hat gar keine get()-Methode.
Ich meine ja auch die Variable in einem Radiobutton! (oder willst Du mich veräppeln?) Die Variable ist zum Zeitpunkt des setzens sehr wohl mit pdaten["nummer"] auszulesen, nur eben später wenn der User sein "OK" geklickt hat, beim Auslesen der Variable um das vom User ausgewählte zu verwerten, nicht mehr!

Code: Alles auswählen

RadioText=pDaten["nachname"]+", "+pDaten["vorname"]+", "+pDaten["nummer"]+", "+pDaten["gebdat"]
R=tk.Radiobutton(wPFrame,text=RadioText, anchor=tk.NW, indicatoron='1',variable=pWahl,value=pDaten)
Wie kann ich den Inhalt von pDaten wieder in ein Dictionary einlesen?
Die Datenfelder sollen dann nämlich per "print" nacheinander ausgegeben werden, damit eine bash-Skript unter Linux diese Daten Zeile für Zeile einliest/übernimmt.
BlackJack

@egerlach: Bitte mal ein vollständiges Beispiel. Falls `pDaten` ein Dictionary ist, ändert sich daran durch den gezeigten Quelltext nichts und man kann danach auch ``pDaten['nummer']`` verwenden. Die Variable heisst aber auch `pWahl`. Und die dürfte wohl kaum vom Typ `dict` sein.

Was sollen eigentlich die ganzen `p`\s vor den Namen?
egerlach
User
Beiträge: 41
Registriert: Samstag 14. März 2009, 21:32

BlackJack hat geschrieben: ... Falls `pDaten` ein Dictionary ist, ändert sich daran durch den gezeigten Quelltext nichts und man kann danach auch ``pDaten['nummer']`` verwenden. Die Variable heisst aber auch `pWahl`. Und die dürfte wohl kaum vom Typ `dict` sein.
hast Recht! Jetzt seh ich es auch, es ist als tk.StingVar() definiert, ich kann mir aber nicht helfen, wie definiere ich denn eine tk.XXXX-Variable, die ein dict ist? tk.{} geht nicht ;-) . Datentypen/ Datenstrukturen richtig definieren kommt bei Python leider zu kurz, weil es nicht erzwungen wird (was Vor- und Nachteile hat)

Code: Alles auswählen

cmd = "ls /home/test/text.ab* -t"
p = subprocess.Popen(cmd, shell=True, #bufsize=1,
    stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p.stdin.close()
dateiListe=p.stdout.read()
#print dateiListe
pWahl=tk.StringVar()         <<<<<==== falsch! Wie gehts besser?
wPFrame = tk.Frame(wParentFrame, relief=tk.SUNKEN, bd=1)
wPFrame.grid(row=1, column=0, ipadx=10, ipady=10, pady=20, sticky=tk.NSEW)
nr=1
#bb=tk.StringVar()
for i in dateiListe.split("\n"):
    if i != "":
        pDaten=lies_Pdaten(i)  #Datei i wird geöffnet und in ein dict eingelesen
        PRadioText=pDaten["nachname"]+", "+pDaten["vorname"]+", "+pDaten["nummer"]+", "+pDaten["gebdat"]
        R=tk.Radiobutton(wPFrame,text=PRadioText, anchor=tk.NW, indicatoron='1',variable=pWahl,value=pDaten)
        R.grid(row=nr, sticky=tk.W)
        if nr == 1: R.select()
        nr+=1
Zuletzt geändert von egerlach am Mittwoch 1. April 2009, 23:24, insgesamt 1-mal geändert.
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo egerlach !

Code: Alles auswählen

import Tkinter as tk

dateiListe = [{'nummer': '1', 
               'nachname': 'Mueller', 
               'vorname': 'Fritz', 
               'gebdat': '15.01.1985',},
              {'nummer': '2', 
               'nachname': 'Mayer', 
               'vorname': 'Peter', 
               'gebdat': '15.02.1986'}]
              
def print_value(daten):
    print daten
    
wParentFrame = tk.Tk()
wPFrame = tk.Frame(wParentFrame, relief=tk.SUNKEN, bd=1)
wPFrame.grid(row=1, column=0, ipadx=10, ipady=10, pady=20, sticky=tk.NSEW)

for row, pDaten in enumerate(dateiListe):
    PRadioText="%s %s %s %s " %(pDaten["nachname"], pDaten["vorname"], 
        pDaten["nummer"], pDaten["gebdat"])
    R=tk.Radiobutton(wPFrame,text=PRadioText, anchor=tk.NW, indicatoron='1', 
        value=pDaten, command=lambda daten=pDaten: print_value(daten))
    R.grid(row=row, sticky=tk.W)
    
wParentFrame.mainloop()
gruss frank
egerlach
User
Beiträge: 41
Registriert: Samstag 14. März 2009, 21:32

vielen Dank für Deine Mühen. Interessante Technik. Allerdings für mich nicht brauchbar, weil der Benutzer in dem Tkinter-Fenster mehrer Dinge auswählen kann. Erst wenn alles ausgewählt/ausgefüllt ist wird ein "ok"-Button geklickt und es soll mit "print" unter anderem auch der Wert dieser Radiobuttons ausgegeben werden. Ich brauche also eine "Speicherfunktion" des gewählten.

Sonst noch jmd eine Idee? - Zur Not parse ich den String eben und füttere damit ein dict oder geben es beim parsen gleich mit "print" aus. Aber sooo schwach kann Python doch nicht sein!!
Ich könnte mir auch vorstellen in dem dictionary über "nummer" zu indizieren, also in der Variablen pWahl (dann definiert als IntVar) nur die "nummer" zu speichern, und dann später eben diese nummer auszuwerten und im dictionary dann die Datenfelder auszulesen. Ich dachte aber mir die Speicherung des dictionary in die Radiobuttons hineinzuverlagern - was evtl. tatsächlich nicht geht. Hier könnte schon die Grenze von Python erreicht sein und die Gunst anderer (komplizierterer) Programmiersprachen beginnen. ;-)
BlackJack

@egerlach: Dann nimm doch einfach eine andere Sprache.

Falls Du bei Python bleiben möchtest: Das ganze in eine Klasse stecken und statt eine Funktion zu benutzen, die die Daten ausgibt, einfach durch eine ersetzen, die die Daten an ein Attribut bindet. So schwer kann das doch nicht sein.

Andere Möglichkeit: die `nr` als Wert zu nehmen und dann am Ende als Index in `datei_liste` verwenden.

Das ist übrigens eine Einschränkung von Tk/Tcl. Die Sprache kennt im Grunde nur Zeichenketten als Datentyp.
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo egerlach !

Du kannst die Lambda-Funktion auch an einen Button binden und mehrere Werte auslesen.

gruss frank
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo egerlach !
Man koennte es auch so loesen.

Code: Alles auswählen


import Tkinter as tk

button_control = list()
auswahl = list()

dateiListe = [{'nummer': '1',
               'nachname': 'Mueller',
               'vorname': 'Fritz',
               'gebdat': '15.01.1985',},
              {'nummer': '2',
               'nachname': 'Mayer',
               'vorname': 'Peter',
               'gebdat': '15.02.1986'},
              {'nummer': '3',
               'nachname': 'Bauer',
               'vorname': 'Hans',
               'gebdat': '12.06.1990'}]
             
def print_value(daten, index):
    button_control[index].config(state="disabled")
    auswahl.append(daten)
    print auswahl
   
wParentFrame = tk.Tk()
wPFrame = tk.Frame(wParentFrame, relief=tk.SUNKEN, bd=1)
wPFrame.grid(row=1, column=0, ipadx=10, ipady=10, pady=20, sticky=tk.NSEW)

for row, pDaten in enumerate(dateiListe):
    PRadioText="%s %s %s %s " %(pDaten["nachname"], pDaten["vorname"],
        pDaten["nummer"], pDaten["gebdat"])
    R=tk.Radiobutton(wPFrame,text=PRadioText, anchor=tk.NW, 
        value=pDaten, command=lambda index=row, daten=pDaten: print_value(daten, index))
    R.grid(row=row, sticky=tk.W)
    R.select()
    button_control.append(R)
  
wParentFrame.mainloop() 
gruss frank
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

@kaytec: Abgesehen von der Wahl der Typen für Nummer und Geburstdatum, was sicherlich am Beispiel liegt, könnte dich das hier interessieren:

Code: Alles auswählen

>>> data={"nummer": "3","nachname":"Mayer", "vorname":"Peter", "gebdat":"15.02.1985"}
>>> "%(nachname)s %(vorname)s %(nummer)s %(gebdat)s" % data
'Mayer Peter 3 15.02.1985'
Das Leben ist wie ein Tennisball.
Antworten