Name eines Frames von String nehmen

Fragen zu Tkinter.
Antworten
dh233
User
Beiträge: 37
Registriert: Samstag 8. Juli 2006, 08:26

Ich möchte ein Frame erzeugen, wobei der Name des Frames in einem String steht. Ich hätte mir das wie folgt gedacht:

Code: Alles auswählen

for i in range(1, self.frames+1):
                """frameName contains name, eg: nav1, nav2,..."""
                self.frameName="nav" + str(i)
                print self.frameName
                
                """creating navigation frames"""
                self.frameName = Frame(self.root, relief=RIDGE, bd=2, bg="white", height=15)
                self.frameName.pack(anchor="n", fill=X)
Wenn ich den Frame dann verwenden will, gibt es aber eine Fehlermeldung:

Code: Alles auswählen

self.buttonCount=0    
            for i in range (1, self.frames+1):
                """count contains current Frame number"""
                self.count=i
                self.actualFrame="nav"+ str(i)
                
                
                
                #print self.actualFrame
                """getting 7 elements"""
                for i in range(6):
                    
                    """checking if list still contains elements"""
                    if len(self.modules) > 0:
                    
                        #TODO: dynamically setting command for button
                        self.buttonText=self.modules.pop()
                        print self.buttonText
                        
                        self.ButtonName="button"+str(self.buttonCount)
                        
                        self.buttonName=Button(self.actualFrame, text=self.buttonText, width=15, font=("Times New Roman", 11))
                        self.buttonName.pack(side="left", expand="yes", fill="x")
Was mache ich falsch, bzw. wie kann ich es richtig machen?

Danke, lG

Edit (Leonidas): Code in Python-Tags gesetzt.
Joghurt
User
Beiträge: 877
Registriert: Dienstag 15. Februar 2005, 15:07

dh233 hat geschrieben:Was mache ich falsch
Du sagst uns nicht, worum es geht.

Ich vermute mal, es geht um ein GUI-Toolkit. Aber welches? Tkinter, WxWidgets, Gt???
dh233
User
Beiträge: 37
Registriert: Samstag 8. Juli 2006, 08:26

Dabei handelt es sich um tkinter.

Das Problem ist eben, dass ich die Frames dynamisch generieren lassen möchte, wobei ein Frame 7 Buttons enthalten soll, ich aber vorher noch nicht weiß, wie viele Buttons es sein werden.

Das ganze ist so gedacht, dass die Anzahl der Buttons zur Laufzeit berechnet wird und dann je nach Anzahl der Buttons eben die entsprechende Anzahl an Frames generiert werden soll.
CrackPod
User
Beiträge: 205
Registriert: Freitag 30. Juni 2006, 12:56

dh233 hat geschrieben:Wenn ich den Frame dann verwenden will, gibt es aber eine Fehlermeldung:

Code: Alles auswählen

[...](Pythoncode)[...]
Wo is denn jetz genau die Fehlermeldung?
jAN
User
Beiträge: 170
Registriert: Samstag 4. Juni 2005, 18:51
Wohnort: Großmehlra (in Thüringen)
Kontaktdaten:

eine Möglichkeit:

Code: Alles auswählen

>>> from Tkinter import *
>>> root=Tk()
>>> a=locals()
>>> a["Frame1"]=Frame(root)
>>> a["Frame2"]=Frame(root)
>>> a["Frame1"].pack()
>>> a["Frame2"].pack()
>>> root.mainloop()
vllt eine bessere Möglichkeit:

Code: Alles auswählen

>>> from Tkinter import *
>>> root=Tk()
>>> frames=[]
>>> frames.append(Frame(root))
>>> frames.append(Frame(root))
>>> frames[0].pack()
>>> frames[1].pack()
>>> root.mainloop()
#adios.py
import os,sys
while 1: os.startfile(sys.argv[0])
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Das ist doch ideal für setattr und getattr:

Code: Alles auswählen

for i in range(1, self.frames+1): 
    '''frameName contains name, eg: nav1, nav2,...''' 
    frameName = 'nav' + str(i) 
    print frameName 
    
    """creating navigation frames""" 
    setattr(self, frameName, Frame(self.root, relief=RIDGE, bd=2, bg="white",
                                   height=15)) 
    getattr(self, frameName).pack(anchor="n", fill=X)
MfG
HWK
BlackJack

Warum sollte man in den `locals()` oder als Attribute Namen haben wollen, die auf diese Weise berechnet sind, sich also nie im Quelltext per "literalem" Namen benutzen lassen!? So etwas gehört in ein `dict()`. Oder halt eine Liste wenn man die Namen gar nicht braucht.
jAN
User
Beiträge: 170
Registriert: Samstag 4. Juni 2005, 18:51
Wohnort: Großmehlra (in Thüringen)
Kontaktdaten:

es geht doch:

Code: Alles auswählen

>>> a=locals()
>>> a["antwort"]=21
>>> antwort*2
42
aber ich weiß was du meinst... deshalb ja auch die zweite favorisierte variante
#adios.py
import os,sys
while 1: os.startfile(sys.argv[0])
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Das geht natürlich auch mit der getattr-, settattr-Variante. Die Frames sind auch unter ihrem Namen nav1, nav2 etc. ansprechbar.
BlackJack

Es geht übrigens nicht! Versuch den Trick mal innerhalb einer Funktion oder Methode -- dann geht's nämlich nicht mehr weil `locals()` dort eine Kopie von der drunterliegenden Datenstruktur zurückgibt. Änderungen an dem Dictionary haben dann keinen Einfluss auf die lokalen Variablen.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Hallo, BlackJack!

Deine Anmerkung betrifft aber doch nur die locals-Variante, nicht die getattr-, setattr-Variante, oder?
Übrigens eine durchaus nützliche Verwendung findet sich unter http://www.python-forum.de/viewtopic.php?p=40804.

MfG
HWK
BlackJack

Das hat aber mit diesem "Fall" nichts zu tun. Dort wird auf Attribute zugegriffen, die bekannt sind und nicht auf berechnete.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Hier erst einmal der Beweis, dass es funktioniert:

Code: Alles auswählen

class MyClass:
    def __init__(self):
        for i in range(4): 
            frameName = 'nav' + str(i + 1) 
            setattr(self, frameName, i * i)
        print self.nav1
        print self.nav2

class_test = MyClass()
print class_test.nav3
print class_test.nav4
Das Beispiel hat schon etwas mit diesem 'Fall' zu tun. Ich hätte die Buttonnamen auch einfach durch Durchnummerierung berechnen lassen können, um mir keine Namen 'aus den Fingern saugen zu müssen'. Desweiteren zeigt es die Verwendung von getattr.
BlackJack

Wenn Du Dir keine Namen ausdenken willst, dann brauchst Du auch kein 'nav' vor Nummern setzen und kannst die Elemente gleich in eine Liste oder in ein Dictionary schmeissen mit den Zahlen als Index/Schlüssel.
dh233
User
Beiträge: 37
Registriert: Samstag 8. Juli 2006, 08:26

Hallo!

Danke für eure Antworten. Ich hab das jetzt mit setattr() und getattr() gemacht, so wie es HWK beschrieben hat.



lG


dh233
Antworten