Tkinter gui erstellung

Fragen zu Tkinter.
rogen

Samstag 26. Juni 2004, 14:35

was mir bei tkinter python fehlte war eine programm mit dem man eine oberfläche erstellen kann.

jetzt schreibe ich mir eines selbst:
es ist noch lange nicht fertig aber es wird..

bitte um kommentar:

Code: Alles auswählen

from Tkinter import * 
from sys import *
global feld


schrift1 = "-*-Curier--R-*--*-140-*-*-*-*-ISO8859-1"
schrift2 = "-*-Times-Bold-R-*--*-240-*-*-*-*-ISO8859-1"

class gui:
    def __init__(self):
        self.root = Tk()
        self.flag = 0
        self.objzahler = 0
        self.felder = []
        self.var1 = StringVar()


        self.obj1=Radiobutton(self.root,width=7,relief='groove',bg='#ffffff',height=1,text='Label',indicatoron='0',variable=self.var1,value="label").place(x=7,y=36)
        self.obj2=Radiobutton(self.root,width=8,relief='groove',bg='#ffffff',height=1,text='Entry',indicatoron='0',variable=self.var1,value="entry").place(x=71,y=37)
        self.obj3=Radiobutton(self.root,width=8,relief='groove',bg='#ffffff',height=1,text='Button',indicatoron='0',variable=self.var1,value="button").place(x=141,y=37)
        self.obj4=Radiobutton(self.root,width=8,relief='groove',bg='#ffffff',height=1,text='Radio',indicatoron='0',variable=self.var1,value="radio").place(x=212,y=37)
        self.obj5=Radiobutton(self.root,width=8,relief='groove',bg='#ffffff',height=1,text='Canvas',indicatoron='0',variable=self.var1,value="canvas").place(x=283,y=37)
        self.obj6=Radiobutton(self.root,width=12,relief='groove',bg='#ffffff',height=1,text='verschieben',indicatoron='0',variable=self.var1,value="move").place(x=354,y=38)
        
        self.obj7=Button(self.root,width=20,relief='groove',bg='#ffffff',height=1,text='Code export',command=self.codemaker).place(x=4,y=71)
        self.obj8=Label(self.root,width=12,relief='groove',bg='#ffffff',height=1,text='Tk fenster').place(x=221,y=76)
        self.entryroot=Entry(self.root,width=12,relief='groove',bg='#ffffff',text='')
        self.entryroot.place(x=308,y=75)
        self.entryroot.insert(0,"self.root")
        self.obj11=Label(self.root,width=62,relief='groove',bg='#ffffff',height=1,text='Gui Tkinter von Gerhard Rogen, v.0.1').place(x=5,y=11)
        self.builder=Canvas(self.root,width=500,relief='groove',bg='#ffffff',height=400)
        self.builder.place(x=13,y=116)
        
        self.builder.bind("<Motion>",self.move)
        self.builder.bind("<Button-1>",self.gedruckt)
        self.builder.bind("<ButtonRelease-1>",self.druckt_los)
        self.root.minsize(550,550)
        
          
        
    def move(self,event):
        global feld
           
        if self.flag==1:
            exec("self.obj" + str(feld) +".move(event.x,event.y)")
           
             
    def gedruckt(self,event):
        global feld
        self.flag = 1
        var = self.var1.get()
        if var == "entry" or var == "label"or var == "button"or var == "canvas"or var == "radio":
            self.objzahler = self.objzahler +1
            exec("self.obj" + str(self.objzahler) +"= objects(self.builder,gu,'"+self.var1.get()+"',event.x,event.y," + str(self.objzahler) +",'"+str(self.entryroot.get())+"')")
            self.felder.append(str(self.objzahler))
            self.flag = 2
           
    def druckt_los(self,event):
        self.flag = 2
        
    def listdel(self,objz):
        print objz
        self.felder.remove(str(objz)) # löschen aus der tabelle
        print self.felder
    def codemaker(self):
        # datei öffnen
        self.fi = file("erste.py","w")
        self.fi.write("from Tkinter import *\n")
        self.fi.write("class neue:\n")
        self.fi.write("     def __init__(self):\n")
        self.fi.write("        "+self.entryroot.get()+" = Tk()\n")
        self.fi.write("        "+self.entryroot.get()+".minsize(500,450)\n")
        # header
        
        
        for f in self.felder:
            exec("neu =  self.obj" + f+".felder()\n")
            self.fi.write("        "+ neu+"\n")
        self.fi.write("        mainloop()\n")
        self.fi.write("neue()\n")
        self.fi.close()

class objects:
    def __init__(self,root,gui,was,xx,yy,name,tkfenster):        
        "Objekte im canvas erstellen"
        self.gui = gui
        self.xx = xx
        self.yy = yy
        self.art = ""
        self.text =""
        self.width = "20"
        self.height = "1"
        self.bg = "#ffffff"
        self.relief = "groove"
        self.bd = "1"
        self.indicatoron = ""
        self.tkfenster = tkfenster
        
        if was == "entry":
            self.zelle = Entry(root,width=self.width)
            self.zelle.bind("<Button-3>",self.edit)
            self.art = "Entry"
        if was == "label":
            self.zelle = Label(root,text="text",width=self.width)
            self.zelle.bind("<Button-3>",self.edit)
            self.text="text"
            self.art = "Label"
        if was == "button":
            self.zelle = Button(root,text="text",width=self.width,bg=self.bg,relief=self.relief,bd=self.bd)
            self.zelle.bind("<Button-3>",self.edit)
            self.text="text"
            self.art = "Button"
        if was == "canvas":
            self.zelle = Canvas(root)
            self.zelle.bind("<Button-3>",self.edit)
            self.text=""
            self.height="100"
            self.width="100"
            self.art = "Canvas"
        if was == "radio":
            self.zelle = Radiobutton(root,indicatoron="0",width=5)
            self.zelle.bind("<Button-3>",self.edit)
            self.text=""
            self.height="1"
            self.width="5"
            self.indicatoron = "0"
            self.art = "Radiobutton"
     
        self.name = name
        self.zelle.place(x=xx,y=yy)
        self.zelle.bind("<Enter>",self.anz)
    def delete(self):
        self.gui.listdel(self.name)
        self.zelle.destroy()
        self.root2.destroy()
    def move(self,xx,yy):
        self.xx = xx
        self.yy = yy
        self.zelle.place(x=xx,y=yy)
    def anz(self,event):
        global feld
        feld = self.name
    def felder(self):
        "sollte einen feld mit den daten zurückgebebne"
        #print "felder------------------"
        #print "self.obj" + str(self.name)
        #print self.art
        #print self.width
        #print self.height
        #print self.bg
        #print self.relief
        #print self.bd
        #print self.xx
        #print self.yy
        feld = "self.obj"+ str(self.name)+"="+self.art+"("+str(self.tkfenster)+","
        feld = feld +"width="+self.width
        feld = feld +",relief='"+self.relief+"'"
        feld = feld +",bg='"+self.bg+"'"
        
        if self.art <> "Entry":
            feld = feld +",height="+self.height
        
        if self.art <> "Canvas":
            feld = feld + ",text='"+self.text+"'"
            
        if self.art == "Radiobutton":
            print self.indicatoron
            feld = feld + ",indicatoron='"+str(self.indicatoron)+"'"
            
        feld = feld +")"+".place(x="+str(self.xx)+",y="+str(self.yy)+")"
        return feld
        
    def edit(self,event):
        print "edit"
        self.root2 = Toplevel()
        self.root2.minsize(290,380)


        self.obj1=Label(self.root2,width=10,relief='groove',bg='#ffffff',height=1,text='width').place(x=10,y=58)
        self.obj2=Label(self.root2,width=10,relief='groove',bg='#ffffff',height=1,text='heigth').place(x=10,y=88)
        self.obj3=Label(self.root2,width=10,relief='groove',bg='#ffffff',height=1,text='text').place(x=11,y=117)
        self.obj4=Label(self.root2,width=10,relief='groove',bg='#ffffff',height=1,text='bgcolor').place(x=11,y=147)
        self.obj5=Label(self.root2,width=10,relief='groove',bg='#ffffff',height=1,text='relief').place(x=12,y=176)
        self.obj6=Label(self.root2,width=10,relief='groove',bg='#ffffff',height=1,text='border').place(x=12,y=206)
        self.obj7=Label(self.root2,width=10,relief='groove',bg='#ffffff',height=1,text='indicator').place(x=13,y=235)
        self.obj8=Label(self.root2,width=10,relief='groove',bg='#ffffff',height=1,text='var für Radio').place(x=13,y=265)
        self.obj19=Label(self.root2,width=40,relief='groove',bg='#ffffff',height=1,text='Edit fenster').place(x=8,y=16)
        
        self.entr1=Entry(self.root2,width=20,relief='groove',bg='#ffffff',text='')
        self.entr1.place(x=104,y=56)
        self.entr2=Entry(self.root2,width=20,relief='groove',bg='#ffffff',text='')
        self.entr2.place(x=105,y=86)        
        self.entr3=Entry(self.root2,width=20,relief='groove',bg='#ffffff',text='')
        self.entr3.place(x=104,y=115)
        self.entr4=Entry(self.root2,width=20,relief='groove',bg='#ffffff',text='')
        self.entr4.place(x=105,y=146)
        self.entr5=Entry(self.root2,width=20,relief='groove',bg='#ffffff',text='')
        self.entr5.place(x=104,y=176)
        self.entr6=Entry(self.root2,width=20,relief='groove',bg='#ffffff',text='')
        self.entr6.place(x=105,y=207)
        self.entr7=Entry(self.root2,width=20,relief='groove',bg='#ffffff',text='')
        self.entr7.place(x=105,y=236)
        self.entr8=Entry(self.root2,width=20,relief='groove',bg='#ffffff',text='')
        self.entr8.place(x=105,y=266)

        self.obj15=Button(self.root2,width=8,relief='groove',bg='#ffffff',command=self.make,height=1,text='aktualisieren').place(x=11,y=347)
        self.obj16=Button(self.root2,width=8,relief='groove',bg='#ffffff',command=self.delete,height=1,text='loschen').place(x=105,y=347)
        self.obj18=Button(self.root2,width=8,relief='groove',bg='#ffffff',command=lambda:self.root2.destroy(),height=1,text='zuruck').place(x=198,y=347)
        


    def make(self):
        if self.entr1.get() <> "":
            self.zelle["width"]=self.entr1.get()
            self.width = self.entr1.get()
        if self.entr2.get() <> "":
            self.zelle["height"]=self.entr2.get()
            self.height = self.entr2.get()
        if self.entr3.get() <> "":
            self.zelle["text"]=self.entr3.get()
            self.text = self.entr3.get()
        if self.entr4.get() <> "":
            self.zelle["bg"]=self.entr4.get()
            self.bg = self.entr4.get()
        if self.entr5.get() <> "":
            self.zelle["relief"]=self.entr5.get()
            self.relief = self.entr5.get()
        if self.entr6.get() <> "":
            self.zelle["bd"]=self.entr6.get()
            self.bd = self.entr6.get()
        if self.entr7.get() <> "":
            self.zelle["indicator"]=self.entr7.get()
            self.bd = self.entr7.get()

  
gu = gui()



mainloop()

Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Samstag 26. Juni 2004, 14:56

Hi. Auf Funktionalität getestet hab ich es noch nicht, aber bei der Methode move gibt es 100%ig einen Fehler (Nonetype object has no Attribute xyz) :wink: . Außerdem scheinen ein paar Einrückungen bei den self.obj durcheinander gekommen zu sein. Zum Rest kann ich gerade nix sagen, da muss ich erst einmal das Programm testen.
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Sonntag 27. Juni 2004, 09:56

Hi rogen!

Hey, das Programm gefällt mir! :D

Habe ein paar Verbesserungs(:?:)vorschläge:

1)

Code: Alles auswählen

self.obj1=Radiobutton(self.root,width=7,relief='groove',bg='#ffffff',height=1,text='Label',indicatoron='0',...
...
Da kann man eingentlich auf die Variablenzuweisung verzichten, Du greifst ja nicht mehr darauf zu, also:

Code: Alles auswählen

Radiobutton(...
...
2)

Code: Alles auswählen

if var == "entry" or var == "label"or var == "button"or var == "canvas"or var == "radio": 
Das sieht so besser aus (finde ich):

Code: Alles auswählen

if var in ["entry", "label", "button", "canvas", "radio"]:
3)

Code: Alles auswählen

if was == "entry":
    self.zelle = Entry(root,width=self.width)
    self.zelle.bind("<Button-3>",self.edit)
    self.art = "Entry"
if was == "label":
    self.zelle = Label(root,text="text",width=self.width)
    self.zelle.bind("<Button-3>",self.edit)
    self.text="text"
    self.art = "Label" 
...
Hier werden immer alle Möglichkeiten geprüft. Besser ist if ... elif ..., weil nach dem ersten Treffer abgebrochen wird. self.zelle.bind("<Button-3>",self.edit) muß auch nicht in jeder Abfrage stehen, es reicht wenn Du's einmal unter dem ganzen if-elif-Block schreibst.

4)
Wenn Variablen nummeriert sind, z.B: self.obj1, self.obj2,..., ist es meist eine gute Idee, ein Array oder Dictionary zu verwenden. Z.B. bei edit in der Klasse objects:

Code: Alles auswählen

def edit(self,event):
		print "edit"
		self.root2 = Toplevel()
		self.root2.minsize(290,380)

		Label(self.root2,width=40,relief='groove',bg='#ffffff',height=1,text='Edit fenster').place(x=8,y=16)
		labs = ["width", "height", "text", "bgcolor", "relief", "border", "indicator", "var für Radio"]
		self.entr = []
		y = 56
		for i in range(8):
			Label(self.root2,width=10,relief='groove',bg='#ffffff',text=labs[i]).place(x=10,y=y)
			self.entr.append(Entry(self.root2,width=20,relief='groove',bg='#ffffff',text=''))
			self.entr[i].place(x=104,y=y)
			y += 30

		Button(self.root2,width=8,relief='groove',bg='#ffffff',
			command=self.make,height=1,text='aktualisieren').place(x=11,y=347)
		Button(self.root2,width=8,relief='groove',bg='#ffffff',
			command=self.delete,height=1,text='loschen').place(x=105,y=347)
		Button(self.root2,width=8,relief='groove',bg='#ffffff',
			command=lambda:self.root2.destroy(),height=1,text='zuruck').place(x=198,y=347)
make wird dann auch etwas kürzer :wink:

Code: Alles auswählen

def make(self):
		keys = ["width","height","text","bg","relief","bd","indicator"]
		for i in range(len(keys)):
			if self.entr[i].get() <> "":
				self.zelle[keys[i]] = self.entr[i].get()
felder müsstest Du dann noch so ändern:

Code: Alles auswählen

def felder(self):
		"sollte einen feld mit den daten zurückgebebne"
		
		feld = "self.obj"+ str(self.name)+"="+self.art+"("+str(self.tkfenster)+","
		feld = feld +"width="+ str(self.zelle["width"])
		feld = feld +",relief='"+self.zelle["relief"]+"'"
		feld = feld +",bg='"+self.zelle["bg"]+"'"

		if self.art <> "Entry":
			feld = feld +",height="+ str(self.zelle["height"])

		if self.art <> "Canvas":
			feld = feld + ",text='"+ self.zelle["text"]+"'"

		if self.art == "Radiobutton":
			print self.zelle["indicatoron"]
			feld = feld + ",indicatoron='"+str(self.zelle["indicatoron"])+"'"

		feld = feld +")"+".place(x="+str(self.xx)+",y="+str(self.yy)+")"
		return feld
Hoffe es war etwas sinnvolles dabel.

Gruß, mawe
rogen

Montag 28. Juni 2004, 13:21

Du hast mich auf ein paar gute ideen gebracht.

durch self.zelle.config() habe ich alles werte ausgelesen und angezeigt.
in jede exportiere zeile habe ich mittels # die configuration in ein dic geschrieben um es besser wieder einlesen zu können.

jetzt fehlt nur noch ein load teil um scripte wieder einzulesen

der code kann jetzt auch in eine datei exportiert werden.


http://rogen.ath.cx/index.php?seite=programme.php
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Montag 28. Juni 2004, 17:23

Hi!
rogen hat geschrieben: Du hast mich auf ein paar gute ideen gebracht.
Freut mich 8)

Noch etwas allgemeines zum Programmierstil:
Ich persönlich hasse (wirklich) überlange Zeilen, wie z.B. bei den Radiobuttons in der Klasse gui. Innerhalb einer Klammer kannst Du die Zeile einfach umbrechen, ansonsten einfach '\' verwenden.

Code: Alles auswählen

Radiobutton(self.root,width=7,relief='groove',bg='#ffffff',
    height=1,text='Label',indicatoron='0',variable=self.var1,
    value="label").place(x=7,y=36)
Aber das ist Geschmackssache.

So, und jetzt schau ich mal, ob ich bei der neuen Version auch etwas zum Herumnörgeln finde... :wink:

mawe
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Montag 28. Juni 2004, 17:57

Hi,

man kannst auch, bei vielen Argumenten, noch etwas übersichtlicher machen.

Code: Alles auswählen

    def Radiobutton(self.root,
                    width=7,
                    relief='groove',
                    bg='#ffffff',
                    height=1,
                    text='Label',
                    indicatoron='0',
                    variable=self.var1,
                    value="label").place(x=7,y=36) 
Gruß

Dookie
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Montag 28. Juni 2004, 18:06

Hi Dookie!
Dookie hat geschrieben: man kannst auch, bei vielen Argumenten, noch etwas übersichtlicher machen.
Stimmt. Ehrlich gesagt mache ich es so wenn ich wenige Argumente hab. Bei so vielen wie im Beispiel zieht mir diese Schreibweise den Code zu weit auseinander, was dann für mich zu unübersichtlich wird (ausserdem hab ich einen etwas kleinen Bildschirm [12 Zoll] was das ganze noch schlimmer macht :?)

Aber wie gesagt: Geschmackssache.

Gruß, mawe
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Montag 28. Juni 2004, 18:34

Hi mawe,

ich hab nen 17" TFT, da geht das natrülich besser und vim (Texteditor) kann ja auch Folding. 8)


Gruß

Dookie
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Dienstag 29. Juni 2004, 06:44

Hi!
Dookie hat geschrieben: ich hab nen 17" TFT, da geht das natrülich besser...
Du Glücklicher.
Dookie hat geschrieben: ...und vim (Texteditor) kann ja auch Folding
Ich verwende auch den vim (Texteditor :wink:), hab aber noch nie Folding benutzt :oops:. Muß mir das mal anschaun.

@rogen:
mawe hat geschrieben: So, und jetzt schau ich mal, ob ich bei der neuen Version auch etwas zum Herumnörgeln finde...
Kleinigkeiten :wink: :
1) Edit-Dialog:
Das Dialogfenster ist etwas zu groß (vor allem bei meinem Bildschirm :?). Vielleicht könntest Du es in ein Frame mit Scrollbars packen?

Ich würde auch die Eigenschafts-Labels anders anordnen, z.B. ganz oben diejenigen, die man meistens braucht (height, width, text, ...) oder zumindest sinnvoll gruppieren, z.B.
width, height
bd, relief
fg, bg, activeforeground, ...
(UPDATE: einige Einträge sind doppelt: fg-foreground, bg-background, bd-borderwidth)

2) generierter Code:
Der Code für jedes Widget ist über-über-über-über-(eimal noch)-über-lang. Vorschlag:

Code: Alles auswählen

for f in self.felder:
    exec("neu =  self.obj" + f+".felder()\n")
    self.fi.write("        "+ ',\n            '.join(neu[0].split(','))+ "\n")
    self.fi.write("        "+ neu[1]+"\n")
Jetzt siehts so aus wie von Dookie vorgeschlagen.

3) Ich weiß nicht ob Du so etwas geplant hast, aber für eine zukünftige Version wäre es schön, wenn man die Größe des Hauptfensters einstellen könnte.

Zum Schluß zitiere ich mich nochmal selbst:
mawe hat geschrieben: Hey, das Programm gefällt mir!
Gruß, mawe
rogen

Dienstag 29. Juni 2004, 08:01

zurzeit bin ich dabei dateien wieder einzulesen und anzuzeigen.

dann probieren ich pwd einzubinden. damit scrolled canvas usw.

das mit den labels eingenschaften geht nicht da ich alles mittels
self.zelle.config() auslese.
rogen

Dienstag 29. Juni 2004, 18:56

habe das programm upgedatet

jetzt kann man eine datei erstellen sie dann veränder wieder einladen usw.

mann kann sogar im idle z.b.
eine klasse hinzufügen und wieder mit dem programm ändern

schauts euch an.

jetzt mache ich noch das canvas variable und dann kann man es gut verwenden. ( glaube ich )
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Mittwoch 30. Juni 2004, 17:24

Hi!

Hmm..., bekomme beim Code-Export die Fehlermeldung, daß die Datei in die ich speichern will nicht existiert. Liegt vielleicht daran, daß codemaker die Datei einlesen will:

Code: Alles auswählen

def codemaker(self):
        datei = datei_auswaehlen("py")
        self.einlese = file(datei,"r")

        block = self.einlese.readlines()
Gruß, mawe
rogen

Mittwoch 7. Juli 2004, 12:55

ich hoffe mir kann jemand helfen

bin dabei Pmw megawidgets einzubauen jetzt muss in dem ordner wo das programm gestartet wird pmw installiert sein.

leider habe ich ein problem:
pmw textfeld funktioniert
pmw scrolledlistbox funktionert nicht richtig
für den text funktioniert component('text')
aber component('listbox') geht nicht
im pmw doc habe ich nichts gefunden....

mfg rogen

Code: Alles auswählen

       if was == "pmwtext":
            self.zelle = Pmw.ScrolledText(root)
            self.art = "Pmw.ScrolledText"
            self.zelle.component('text').bind('<3>', self.edit)
            self.PmwComponent = "text"
            self.zelle.component(self.PmwComponent).bind('<3>', self.edit)
        elif was == "pmwlistbox":
            print "listbox"
            self.zelle = Pmw.ScrolledText(root)
            self.art = "Pmw.ScrolledListBox"
            self.zelle.component('text')["width"] = 20
            self.zelle.component('text')["height"] = 20
            self.zelle.component('text').bind('<3>', self.edit)
            self.PmwComponent = "text"
            self.zelle.component(self.PmwComponent).bind('<3>', self.edit)
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Mittwoch 7. Juli 2004, 17:48

Hi!

Also ganz schlau werd ich aus deiner Frage nicht.

Code: Alles auswählen

elif was == "pmwlistbox":
            print "listbox"
            self.zelle = Pmw.ScrolledText(root) 
Sollte da jetzt nicht self.zelle = Pmw.ScrolledListBox(root) stehen?
rogen hat geschrieben: aber component('listbox') geht nicht
Das kommt ja in dem Beispiel gar nicht vor?!
Schreib bitte etwas genauer was nicht funktioniert (ich brauch immer etwas länger um's zu kapieren :wink:).

PS:
rogen hat geschrieben: bin dabei Pmw megawidgets einzubauen jetzt muss in dem ordner wo das programm gestartet wird pmw installiert sein.
Im gleichen Ordner? Es reicht doch wenn Pmw im PYTHONPATH installiert ist, oder versteh ich das schon wieder falsch?

Gruß, mawe
Antworten