[Python-de] dynamisch Inhalte einfuegen

Peter Otten __peter__ at web.de
Fre Apr 1 09:39:51 CEST 2005


Am Donnerstag, 31. März 2005 21:11 schrieb Mike Abel:

> Die Erzeugung der Textwidgets gelingt, aber beim zuweisen der Inhalte
> schlägt der Fehlerteufel zu.

> #! /usr/bin/env python
>
> import Tkinter
> from Tkconstants import *
>
> tk = Tkinter.Tk()
> tk.geometry("500x250+0+0")
> menubar = Tkinter.Menu(tk)
>
> Master_d = {}
> Master_d[1] = "e"
> Master_d[2] = "f"
> Master_d[3] = "g"
>
# hier einfügen:

e = "irgendwas"
f = "nochwas"
g = "nochirgendwas"

>
> def view_db():
>     top_view = Tkinter.Toplevel()
>     top_view.geometry("1024x768+0+0")
>
>     # Textwidgets erzeugen
>     for i in range(1,4):
>         exec "text_" + str(i) + "= Tkinter.Text(top_view,height=2)"
>         exec "text_" + str(i) + ".pack()"
>
>     # Inhalte zuweisen
>     for i in range(1,4):
>         m = Master_d[i]
>         exec "text_" + str(i) + ".insert(\"1.0\"," + m + ")"
>
>
> viewmenu = Tkinter.Menu(menubar, tearoff=0)
> viewmenu.add_command(label=" view ", command=view_db)
> menubar.add_cascade(label="View", menu=viewmenu, underline=0)
> tk.config(menu=menubar)
> tk.mainloop()
>
>
>
> Exception in Tkinter callback
> Traceback (most recent call last):
>   File "/usr/lib/python2.3/lib-tk/Tkinter.py", line 1345, in __call__
>     return self.func(*args)
>   File "/home/mike/d.py", line 23, in view_db
>     exec "text_" + str(i) + ".insert(\"1.0\"," + m + ")"
>   File "<string>", line 1, in ?
> NameError: name 'e' is not defined

NameError sagt es bereits, es gibt keine Variable mit dem Namen e (und f und 
g). 

> Hat jemand Erfahrung bei ähnlichen Problemstellungen (dynamische
> Erzeugung von Widgets und deren Handling) und deren Lösung?
> Wie kann man untenstehendes Problem lösen?

Mit den exec statements mehr führst Du mehr "Dynamik" ein als dem Programm gut 
tut. Deshalb hier eine Variante, die ohne exec auskommt:

import Tkinter
from Tkconstants import *

tk = Tkinter.Tk()
tk.geometry("500x250+0+0")
menubar = Tkinter.Menu(tk)

initial_values = ["alpha", "beta", "gamma"]
widgets = []

def view_db():
    top_view = Tkinter.Toplevel()
    top_view.geometry("1024x768+0+0")
    widgets[:] = [] #XXX sollte beim Schliessen des Fensters passiert sein
    # Textwidgets erzeugen
    for value in initial_values:
        t = Tkinter.Text(top_view, height=2)
        t.insert("1.0", value)
        t.pack()
        # um spaeter die aktualisierten Werte auslesen zu koennen:
        widgets.append(t) 

viewmenu = Tkinter.Menu(menubar, tearoff=0)
viewmenu.add_command(label=" view ", command=view_db)
menubar.add_cascade(label="View", menu=viewmenu, underline=0)
tk.config(menu=menubar)
tk.mainloop()

Noch zwei Bemerkungen:

* Indizes starten in Python wie in C mit 0. Auch wenn Dich bei Dictionaries 
niemand dazu zwingt -- Abweichungen von der Konvention sind unnötige 
Fehlerquellen.
* for-Schleifen 
    for index in range(len(sequence)):
        # ...
  können meistens durch das übersichtlichere
    for item in sequence:
       # ...
  ersetzt werden. 

Peter