Entry und int(get)

Fragen zu Tkinter.
Antworten
raibel
User
Beiträge: 30
Registriert: Mittwoch 15. November 2006, 22:03

Hallo!

Hilfe, ich finde einfach keinen Lösungsansatz.
Es werden Zahlen in Entry's eingegeben, über ein dict zwischengespeichert und dann als int-werte weiterverarbeitet.Das funktioniert auch soweit, allerdings mit folgender Einschränkung.

Beispiel:

Code: Alles auswählen

import Tkinter as tk

class Test():
    def __init__(self):
        self.dict = {}
        for i in range(1):
            for j in range(10):
                ent = tk.Entry()
                ent.grid(column=i, row=j)
                ent.insert(tk.END, '0')             #==1==
                self.dict[i, j] = ent
                ent.bind('<KeyPress-Tab>', self.calc)

    def calc(self, event):        
        for i in range(1):
            for j in range(10):
                k = i, j
                print int(self.dict.get(k).get())  #==2==
                
root = tk.Tk()
t = Test()
root.mainloop()
Die Ausgabe bei ==2== funktioniert nur, wenn ich vorher über insert (==1==) eine Zahl eingebe. Egal ob mit oder ohne Kommata. Diese Zahl steht dann in allen Entry's bevor ich was eingebe. Wie gesagt, es funktioniert zwar, aber das kann so nicht richtig sein.
Ohne insert (==1==) kommt folgende Fehlermeldung:

Code: Alles auswählen

    print int(self.dict.get(k).get())  # ==2==
ValueError: invalid literal for int() with base 10: ''
Das Problem ist wohl, das nach Eingabe über TAB-event in der Funktion "calc" alle Entry's durchlaufen werden und die Entry's, bei denen noch kein Wert eingegeben ist, einen String zurückliefern.

Hat jemand eine Lösung, wie ich die Nullen da rausbekomme?

Grüße

rai
BlackJack

Nicht nur die `Entry`\s bei denen kein Wert eingegeben wurde, geben eine Zeichenkette zurück, sondern *alle*. Wenn nichts drin steht, ist das logischerweise eine leere Zeichenkette. Eben genau das, was im `Entry` steht.

In dem Beispiel könnte man die Ausnahme einfach entsprechend behandeln.
raibel
User
Beiträge: 30
Registriert: Mittwoch 15. November 2006, 22:03

Guten Morgen! :)

Ja, klar. Es wird immer eine Zeichenkette zurückgegeben.
Ich kann unter ==2== nur zur ganzen Zahl konvertieren, wenn in allen Entry's
eine Zahl steht. Egal ob als String oder als Zahl.
In dem Beispiel könnte man die Ausnahme einfach entsprechend behandeln.
Welche Ausnahme und wie behandeln?

Ich habe im Hauptprogramm 124 "Entry's". Mit der vorgegebenen "Null" funktioniert alles.
Ich hab nur das Problem, wenn ich die, mit pickle vorher gesicherten, Int-Werte wieder einlese die "Null" drangehängt wird und die ganze Auswertung nicht mehr hinhaut.
Es wäre wahnsinnig umständlich erst alle einzelnen "Entry-Werte" rauszuiterieren, dann zu Integer zu konvertieren, dann den einzelnen "Entry's" wieder zuzordnen, um dann damit rechnen zu können.

Gibt es wirklich keine andere Möglichkeit?

Grüße

rai
BlackJack

Die Ausnahme, die Du bekommst, ist ja der `ValueError`. Auf den musst Du an der entsprechenden Stelle reagieren.

Die Beschreibung klingt ein bisschen so, als wenn Du mit den Inhalten der `Entry`\s rechnen willst, also das die `Entry`\s die "Datenstruktur" sind, in denen die Werte gespeichert werden. Das ist in der Tat umständlich und nicht gerade der saubere Weg. Die GUI ist zum anzeigen und eingeben von Daten gedacht, nicht als Aufbewahrungsort.

Programmlogik und GUI sollte man trennen.
raibel
User
Beiträge: 30
Registriert: Mittwoch 15. November 2006, 22:03

Ich poste mal einen Auszug:

Code: Alles auswählen

        self.list_get = {} # =8= hier sind die Daten zum pickle'n hinterlegt
    def calc(self, event):
        list_sum = [] # =4= Liste 
        for i in xrange(2, 33):
            a_key = i, 1    ;     b_key = i, 2    
            c_key = i, 3    ;     d_key = i, 4
            a_get = int(self.dic.get(a_key).get()) # =1= hier die Daten aus den Entry's, wie im Beispiel 
            b_get =int(self.dic.get(b_key).get()) # allerdings 4x31 Felder
            c_get = int(self.dic.get(c_key).get())
            d_get = int(self.dic.get(d_key).get())
            self.list_get[a_key] = a_get # =7= von hier aus zum dict(=8=)
            self.list_get[b_key] = b_get
            self.list_get[c_key] = c_get
            self.list_get[d_key] = d_get
            
            x = c_get - a_get # =2=  hier mit den Daten rechnen
            y = d_get - b_get
            z = x*60+y
            list_sum.append(z) # =3= hier werden die Daten(Minuten) in der Liste(=4=) gespeichert
            s = sum(list_sum) # =5= und hier aus der Liste addiert 
        
        self.listbox.insert(tk.END, '%5d:%02d' % divmod(s, 60)) # =6= hier als Std.:Min.(00:00) ausgegeben
        self.listbox.delete(0, tk.END)
        self.listbox.insert(tk.END, '%5d:%02d' % divmod(s, 60)) 
        
Ist im Prinzip alles so wie im Beispiel. Was kann, muss ich tun, um bei (=1=) zu Integer konvertierbare Zeichen zu bekommen, ohne vorher über insert eine Zahl einzugeben? Wäre ne Super Lösung.
Ich will doch nur die "Null" weghaben :cry:!

Mit Bitte um Denkanstoss.

Grüße

rai
BlackJack

Schreib Dir doch einfach eine Methode die zu einem `Entry`-Exemplar die entsprechende Zahl liefert. Also dass was drin steht in eine Zahl gewandelt, bzw. eine Null falls diese Umwandlung nicht funktioniert.
raibel
User
Beiträge: 30
Registriert: Mittwoch 15. November 2006, 22:03

@ BlackJack
Danke erstmal. Ich denk drüber nach. Muss jetzt zur Arbeit.

Meld mich wieder.

Grüße

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

Vielleicht übersehe ich irgendetwas, aber die einfachste Lösung - sofern man nicht größere Eingriffe vornehmen will - sieht m.E. so aus:

Wenn du ==2== so machst:

Code: Alles auswählen

print int(self.dict.get(k).get() or 0)
Dann kannst du das Befüllen mit den Nullen in ==1== lassen und es sollte so funktionieren, wie du es möchtest.
raibel
User
Beiträge: 30
Registriert: Mittwoch 15. November 2006, 22:03

@ püton

That's it! :P

Genau so eine Lösung habe ich gesucht. Einfach und ergreifend.

Vielen Dank dafür!!!

Grüße

rai
Antworten