Fragen zu Tkinter

Fragen zu Tkinter.
Antworten
12052007
User
Beiträge: 8
Registriert: Dienstag 11. Dezember 2007, 14:57

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]
BlackJack

Der Quelltext passt nicht zum Bild. Der gibt gar kein Bild, sondern einen `NameError` weil `tab1` nicht definiert ist.
12052007
User
Beiträge: 8
Registriert: Dienstag 11. Dezember 2007, 14:57

Hier der komplette Quelltext: http://paste.pocoo.org/show/15091/

Edit (BlackJack): Code ausgelagert.
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.
12052007
User
Beiträge: 8
Registriert: Dienstag 11. Dezember 2007, 14:57

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?
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.
12052007
User
Beiträge: 8
Registriert: Dienstag 11. Dezember 2007, 14:57

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()
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.
12052007
User
Beiträge: 8
Registriert: Dienstag 11. Dezember 2007, 14:57

Und was muss ich jetzt konkret schreiben, damit es funktioniert?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

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.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten