Seite 1 von 1

Fragen zu Tkinter

Verfasst: Dienstag 11. Dezember 2007, 15:23
von 12052007
Hallo,
ich arbeite an einem "Geometrie-Widget".
Die Fragen werden zwar unter eurer Würde sein, aber die Boardsuche konnte mir bei diesem Thema nicht helfen.

Code: Alles auswählen

# -*- coding: cp1252 -*-
from Tkconstants import N, S, W, E
from Tix import Tk, NoteBook, Label, Entry, Button, Canvas
 
 

root = Tk()
 

meinNotebook = NoteBook(root, ipadx=5, ipady=5)
meinNotebook.grid(row=0, column=0, sticky=N+S+W+E)
 

def f11():
    l=float(txt_L.get())
    b=float(txt_B.get())
    lab_EA.config(text=str(l*b))
    
def f12():
    l=float(txt_L.get())
    b=float(txt_B.get())
    lab_FB.config(text=str((1/3)*(b**2)*l))


lab_L=Label(tab1, text="Höhe:")
lab_L.grid(row=0, column=0)

lab_B=Label(tab1, text="Breite:")
lab_B.grid(row=1, column=0)

txt_L=Entry(tab1)
txt_L.grid(row=0, column=1)
txt_B=Entry(tab1)
txt_B.grid(row=1, column=1)

but_L=Button(tab1, text='Oberfläche:', command = f11)
but_L.grid(row=2, column=0)

but_C=Button(tab1, text='Volumen:', command = f12)
but_C.grid(row=3, column=0)

lab_EA=Label(tab1, text="-")
lab_EA.grid(row=2, column=1)

lab_FB=Label(tab1, text="-")
lab_FB.grid(row=3, column=1)

maxX=640.  
maxY=480. 
canvas=Canvas(tab1, width=maxX, height=maxY, bg='white')
canvas.grid(row=5, column=0, columnspan=3)
canvas.create_line(400, 440, 520, 280)
canvas.create_line(520, 280, 280, 280)
canvas.create_line(160, 440, 280, 280)
canvas.create_line(160, 440, 400, 440)
canvas.create_line(160, 440, 520, 280)
canvas.create_line(280, 280, 400, 440)
canvas.create_line(340, 360, 340, 120)
canvas.create_line(340, 120, 160, 440)
canvas.create_line(340, 120, 280, 280)
canvas.create_line(340, 120, 400, 440)
canvas.create_line(340, 120, 520, 280)
1. Was muss ich tun, damit Oberfläche und Volumen berechnet werden, wenn ich die Buttons betätige?

2. Wie kann ich die Zeichnung und den Text ganz nach links verschieben?
(rote Pfeile)

3. Wie kann ich die beiden "-" entfernen? (rote Kreise)

Bild[/img]

Verfasst: Dienstag 11. Dezember 2007, 16:27
von BlackJack
Der Quelltext passt nicht zum Bild. Der gibt gar kein Bild, sondern einen `NameError` weil `tab1` nicht definiert ist.

Verfasst: Dienstag 11. Dezember 2007, 16:33
von 12052007
Hier der komplette Quelltext: http://paste.pocoo.org/show/15091/

Edit (BlackJack): Code ausgelagert.

Verfasst: Dienstag 11. Dezember 2007, 16:55
von BlackJack
1. Die Funktionen greifen auf die Entries zu die an die Namen `txt_L` und `text_B` zum Zeitpunkt des *Aufrufs* der Funktion gebunden sind. Das wären dann die ab Zeile 245 erzeugten.

3. Die '-' kannst Du entfernen, indem Du sie nicht explizit dort hin setzt. Ich habe beim drüberschauen mindestens eine Stelle gefunden, bin aber jetzt zu faul nochmal zu suchen. Das kannst Du auch selbst, am besten mit Hilfe der Suchfunktion Deines Editors machen.

Letztendlich ist IMHO viel zu viel Quelltext auf Modulebene in diesem Programm. Das sollte man mittels Funktionen oder gar Klassen oder Modulen in kleinere Häppchen aufteilen. Dann besteht die Gefahr nicht, dass man bei dem Quelltext für ein Tab in einem anderen Tab aus versehen irgendwelche '-' setzt.

Verfasst: Mittwoch 12. Dezember 2007, 16:11
von 12052007
1. Die Funktionen greifen auf die Entries zu die an die Namen `txt_L` und `text_B` zum Zeitpunkt des *Aufrufs* der Funktion gebunden sind. Das wären dann die ab Zeile 245 erzeugten.
Was muss ich also tun, damit die Funktionen auch berechnet werden?
Die '-' kannst Du entfernen, indem Du sie nicht explizit dort hin setzt.
Ich wollte sie ja auch nicht explizit dahin setzen, sondern nur zwei haben:

Code: Alles auswählen

lab_EA=Label(tab1, text="-")
lab_EA.grid(row=2, column=1)

lab_FB=Label(tab1, text="-")
lab_FB.grid(row=3, column=1)
Trotzdem zeigt das Programm die in rot eingekreisten. Warum?

Verfasst: Mittwoch 12. Dezember 2007, 17:07
von BlackJack
1. Dafür sorgen, dass die richtigen Entries verwendet werden. Wenn Du einen Namen an ein anderes Objekt bindest, ist das Objekt was vorher an diesen Namen gebunden war logischerweise nicht mehr über diesen Namen erreichbar.

Code: Alles auswählen

def f():
    print x

x = 'foo'
x = 'bar'

f() # => gibt 'bar' aus.
Die einfachste, halbwegs saubere Lösung wäre es wohl das Erstellen des Inhalts eines Tabs in eine Funktion zu stecken und die Berechnungen als lokale Funktionen zu definieren. Damit haben die Tabs quasi ihren eigenen Namensraum und die Berechnung greift auf die lokalen Namen der Entries zu.

2. Das Programm zeigt die rot eingekreisten '-' weil Du sie in Deinem Programm dort hin setzt. Lass das einfach, dann werden sie auch nicht mehr angezeigt. Such in Deinem Quelltext einfach mal nach ``tab1, text="-"`` und Du wirst es nicht zwei mal sondern vier mal finden. Zwei davon sind offenbar falsch. Wenn Du die Tabs mal durchgehst, fehlen die an anderer Stelle.

Auch das Problem hätte man nicht, wenn nicht alles im Namensraum des Moduls stecken würde.

Verfasst: Mittwoch 12. Dezember 2007, 20:12
von 12052007
1. Dafür sorgen, dass die richtigen Entries verwendet werden. Wenn Du einen Namen an ein anderes Objekt bindest, ist das Objekt was vorher an diesen Namen gebunden war logischerweise nicht mehr über diesen Namen erreichbar.
Tut mir Leid, aber ich verstehe immer noch nicht wie diese Fehlermeldung zu stande kommt:

l=float(txt_L.get())
ValueError: empty string for float()

Verfasst: Mittwoch 12. Dezember 2007, 20:18
von BlackJack
`txt_L.get()` holt eine Zeichenkette aus dem `Entry` und das wird dann versucht mit `float()` in eine Zeichenkette umzuwandeln. Wenn diese Zeichenkette leer ist, dann kommt die Fehlermeldung:

Code: Alles auswählen

In [515]: float('')
---------------------------------------------------------------------------
<type 'exceptions.ValueError'>            Traceback (most recent call last)

/home/bj/<ipython console> in <module>()

<type 'exceptions.ValueError'>: empty string for float()
`txt_L` ist das `Entry`, das als *letztes* an diesen Namen gebunden wurde. Also nicht mehr das, welches im ersten Tab angezeigt wird.

Verfasst: Mittwoch 12. Dezember 2007, 20:31
von 12052007
Und was muss ich jetzt konkret schreiben, damit es funktioniert?

Verfasst: Mittwoch 12. Dezember 2007, 22:19
von Leonidas
Du musst eben verhindern, dass diese Zeile ausgeführt wird, wenn das Entry leer ist. Da gibt es mehrere Möglichkeiten: du kannst eine Abfrage machen, die checkt ob dort was steht oder den Benutzer unter Androhung physischer Gewalt (ein Baseballschläger zeigt meist gute Wirkung) zwingen da etwas einzutippen.