@ Alfons Mittelmayer: Wenn ich das jetzt richtig verstehe, kann ich also in Tkinter (ohne GUI Designer) einen Frame erzeugen, welcher die benötigten Buttons beinhaltet. Dieser Frame ist zunächst nicht sichtbar und wird durch Betätigung eines anderen Buttons durch eine Zeitverzögerung von unten nach oben eingeblendet. Anschließend kann der Frame durch nochmaliges Betätigen des Buttons ausgeblendet werden.
Das wäre genau das was ich brauche
Wie kann ich eine solche zeitgesteuerte Verschiebung erzeugen?
Wischfunktion durch Buttonklick hervorrufen
@Alfons: moderne UI-Frameworks & Browser haben eine Menge Zeit und Code darin investiert, solche Animationssystem zu entwickeln. Mit GPU-Beschleunigung (gerade im dem mobilen Sektor sehr wichtig, und der PI IST ein Mobilprozessor) und entsprechenden Abstraktionen. Es gibts natürlich immer ein paar Schlaumeier die glauben, sie können alles besser als der Rest. Wohlan, mach.
Deine Exception liefere ich gerne nach.
Deine Exception liefere ich gerne nach.
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Hier ein Beispiel. Das Beispiel zeigt das Prinzip, ist aber kein Beispiel für schöne OOP:apple hat geschrieben:Wie kann ich eine solche zeitgesteuerte Verschiebung erzeugen?
Code: Alles auswählen
import tkinter as tk
move_element = None
move_yi = 0
move_yn = 0
move_step = -1
def do_move():
timestep=3
global move_element
global move_yi
global move_yn
global move_step
move_yi = move_yi + move_step
move_element.place(y=move_yi)
if move_yn != move_yi:
move_element.after(timestep,do_move)
def wish(element,y0,yn,step):
global move_element
move_element=element
global move_yi
move_yi=y0
global move_yn
move_yn=yn
global move_step
move_step=step
do_move()
class Application(tk.Tk):
def __init__(self,**kwargs):
tk.Tk.__init__(self,**kwargs)
self.geometry("280x370")
self.labelFrame = Labelframe(self,**{'width': 200, 'text': 'Screen', 'bd': 0, 'relief': 'flat', 'bg': '#d949d9', 'height': 300})
self.labelFrame.place(**{'y': '28', 'x': '43'})
class Labelframe(tk.LabelFrame):
def __init__(self,master,**kwargs):
tk.LabelFrame.__init__(self,master,**kwargs)
tk.Button(self,text='wish on',command=self.wish_on).place(y=243,x=50)
self.labelFrame = Labelframe_1(self,**{'width': 200, 'text': 'Noch ein Fenster', 'bd': 0, 'relief': 'flat', 'bg': '#d9d93c', 'height': 150})
self.labelFrame.place(**{'y': '300', 'x': '0'})
def wish_on(self):
wish(self.labelFrame,300,140,-1)
class Labelframe_1(tk.LabelFrame):
def __init__(self,master,**kwargs):
tk.LabelFrame.__init__(self,master,**kwargs)
tk.Button(self,text='wish off',command=self.wish_off).place(y=83,x=50)
def wish_off(self):
wish(self,140,300,1)
Application().mainloop()
Wie versprochen, die exception. Das man die main.py nicht aufrufen ausser man steht im Verzeichnis in dem sie liegt ist sicher gewollt?
Code: Alles auswählen
dir@client2087 /tmp $ python3.5 python-gui-messaging/GuiDesigner/main.py
Couldn't open file: guidesigner/Guidesigner.py
^CTraceback (most recent call last):
File "python-gui-messaging/GuiDesigner/main.py", line 2, in <module>
tk.Tk().mainloop('guidesigner/Guidesigner.py')
File "/private/tmp/python-gui-messaging/GuiDesigner/DynTkInter.py", line 901, in mainloop
StatTkInter.Tk.mainloop(self)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/tkinter/__init__.py", line 1131, in mainloop
self.tk.mainloop(n)
KeyboardInterrupt
dir@client2087 /tmp $ cd python-gui-messaging/GuiDesigner/
dir@client2087 /tmp/python-gui-messaging/GuiDesigner (master =) $ python3.5 main.py
Exception in Tkinter callback
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/tkinter/__init__.py", line 1550, in __call__
return self.func(*args)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/tkinter/__init__.py", line 596, in callit
func(*args)
File "/private/tmp/python-gui-messaging/GuiDesigner/DynTkInter.py", line 2601, in DynLoad
exec(evcode)
File "guidesigner/Guidesigner.py", line 1, in <module>
Toplevel("DynTkInterGuiDesigner",title="DynTkInter GuiDesigner",geometry='+30+20',link="guidesigner/Modules.py")
File "/private/tmp/python-gui-messaging/GuiDesigner/DynTkInter.py", line 926, in __init__
master = _initGuiContainer(kwargs,StatTkInter.Toplevel,self,myname,"toplevel",True,True,None,_TopLevelRoot._container)
File "/private/tmp/python-gui-messaging/GuiDesigner/DynTkInter.py", line 827, in _initGuiContainer
GuiContainer.__init__(element,myname,select,mayhave_grid,isMainWindow,tkmaster,**kwargs)
File "/private/tmp/python-gui-messaging/GuiDesigner/DynTkInter.py", line 604, in __init__
FileImportContainer(self) # if link != ""
File "/private/tmp/python-gui-messaging/GuiDesigner/DynTkInter.py", line 788, in FileImportContainer
DynLoad(container.link)
File "/private/tmp/python-gui-messaging/GuiDesigner/DynTkInter.py", line 2601, in DynLoad
exec(evcode)
File "guidesigner/Modules.py", line 57, in <module>
LabelFrame('BaseLayout',text="""Layout""",link="guidesigner/BaseLayout.py")
File "/private/tmp/python-gui-messaging/GuiDesigner/DynTkInter.py", line 1102, in __init__
_initGuiContainer(kwargs,StatTkInter.LabelFrame,self,myname,"labelframe",True)
File "/private/tmp/python-gui-messaging/GuiDesigner/DynTkInter.py", line 827, in _initGuiContainer
GuiContainer.__init__(element,myname,select,mayhave_grid,isMainWindow,tkmaster,**kwargs)
File "/private/tmp/python-gui-messaging/GuiDesigner/DynTkInter.py", line 604, in __init__
FileImportContainer(self) # if link != ""
File "/private/tmp/python-gui-messaging/GuiDesigner/DynTkInter.py", line 788, in FileImportContainer
DynLoad(container.link)
File "/private/tmp/python-gui-messaging/GuiDesigner/DynTkInter.py", line 2601, in DynLoad
exec(evcode)
File "guidesigner/BaseLayout.py", line 7, in <module>
LabelFrame('GridLayout',link="guidesigner/GridLayout.py")
File "/private/tmp/python-gui-messaging/GuiDesigner/DynTkInter.py", line 1102, in __init__
_initGuiContainer(kwargs,StatTkInter.LabelFrame,self,myname,"labelframe",True)
File "/private/tmp/python-gui-messaging/GuiDesigner/DynTkInter.py", line 827, in _initGuiContainer
GuiContainer.__init__(element,myname,select,mayhave_grid,isMainWindow,tkmaster,**kwargs)
File "/private/tmp/python-gui-messaging/GuiDesigner/DynTkInter.py", line 604, in __init__
FileImportContainer(self) # if link != ""
File "/private/tmp/python-gui-messaging/GuiDesigner/DynTkInter.py", line 788, in FileImportContainer
DynLoad(container.link)
File "/private/tmp/python-gui-messaging/GuiDesigner/DynTkInter.py", line 2599, in DynLoad
code = handle.read()
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/encodings/ascii.py", line 26, in decode
return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 20599: ordinal not in range(128)
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/tkinter/__init__.py", line 1550, in __call__
return self.func(*args)
File "/private/tmp/python-gui-messaging/GuiDesigner/DynTkInter.py", line 933, in destroy
GuiElement.destroy(self)
File "/private/tmp/python-gui-messaging/GuiDesigner/DynTkInter.py", line 298, in destroy
if widget_exists(self): self.tkClass.destroy(self)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/tkinter/__init__.py", line 2146, in destroy
if self._name in self.master.children:
AttributeError: '_CreateTopLevelRoot' object has no attribute 'children'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "main.py", line 2, in <module>
tk.Tk().mainloop('guidesigner/Guidesigner.py')
File "/private/tmp/python-gui-messaging/GuiDesigner/DynTkInter.py", line 901, in mainloop
StatTkInter.Tk.mainloop(self)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/tkinter/__init__.py", line 1131, in mainloop
self.tk.mainloop(n)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/tkinter/__init__.py", line 1554, in __call__
self.widget._report_exception()
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/tkinter/__init__.py", line 1297, in _report_exception
root.report_callback_exception(exc, val, tb)
AttributeError: '_CreateTopLevelRoot' object has no attribute 'report_callback_exception'
dir@client2087 /tmp/python-gui-messaging/GuiDesigner (master =) $0
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Nein , ist nicht gewollt, bzw. ich war mir nicht bewusst, dass jemand nicht in das Verzeichnis selber gehen will. Danke, da kann man dann das noch in main.py einfügen:__deets__ hat geschrieben:Das man die main.py nicht aufrufen ausser man steht im Verzeichnis in dem sie liegt ist sicher gewollt?
Code: Alles auswählen
import os
os.chdir(os.path.dirname(os.path.realpath(__file__)))
@__deets__: besser keine Diskussion anfangen, das ist verschwendete Lebenszeit .
@Alfons Mittelmeyer: global sollte in keinem Programm vorkommen. Zumal das meiste davon unnütz ist. Wenn Du schon eine Labelframe_1-Klasse hast, dann könntest Du sie auch nutzen. Du hast immer noch diese unmöglich komplizierte Variante, Schlüsselwortargumente zu übergeben, dass man es nicht lesen möchte. So nichtsagende Namen wie Labelframe_1 sollte man auch nicht benutzen.
Soetwas einem Anfänger zu zeigen, halte ich nicht für gut, das könnte jemand für brauchbar halten.
@Alfons Mittelmeyer: global sollte in keinem Programm vorkommen. Zumal das meiste davon unnütz ist. Wenn Du schon eine Labelframe_1-Klasse hast, dann könntest Du sie auch nutzen. Du hast immer noch diese unmöglich komplizierte Variante, Schlüsselwortargumente zu übergeben, dass man es nicht lesen möchte. So nichtsagende Namen wie Labelframe_1 sollte man auch nicht benutzen.
Soetwas einem Anfänger zu zeigen, halte ich nicht für gut, das könnte jemand für brauchbar halten.
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
@__deets__: os.chdir ändert nicht das Arbeitsverzeichnis für die Shell. Etwa nach Beendigung von "python3 GuiDesigner/main.py" steht die Shell wieder auf dem ursprünglichen Arbeitsverzeichnis, auch wenn innerhalb von main.py, dieses durch os.chdir geändert wurde. Python stelllt also bei Beendigung das ursprüngliche Arbeitsverzeichnis der Shell wieder her.
Meine Ansicht: eine Anwendung sollte ein Arbeitsverzeichnis haben und daher sollte man ein solches durchaus in der Anwendung setzen dürfen, anstatt etwa ständig explizit eine Variable für einen Basispfad anzugeben oder zuvor in der Shell es mit cd zu verstellen.
Meine Ansicht: eine Anwendung sollte ein Arbeitsverzeichnis haben und daher sollte man ein solches durchaus in der Anwendung setzen dürfen, anstatt etwa ständig explizit eine Variable für einen Basispfad anzugeben oder zuvor in der Shell es mit cd zu verstellen.
@Alfons Mittelmeyer: Python stellt gar nichts wieder her. Es wurde nichts ausserhalb des Prozesses verändert was wiederhergestellt werden müsste.
Das Arbeitsverzeichnis wird vom Aufrufer vorgegeben. Anwendungen die das anders handhaben verhalten sich anders als der Benutzer das erwartet, weil das so gut wie keine Anwendung macht. Ausnahmen sind die Anwendungen von Programmierern die immer alles anders machen wollen.
Das Arbeitsverzeichnis wird vom Aufrufer vorgegeben. Anwendungen die das anders handhaben verhalten sich anders als der Benutzer das erwartet, weil das so gut wie keine Anwendung macht. Ausnahmen sind die Anwendungen von Programmierern die immer alles anders machen wollen.
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Das brauchst Du mir nicht sagen, sondern dem Anfänger. Dieser sollte diese Globalen Variablen und die Funktion do_move und eventuell auch wish in einer Klasse kapseln. wish kann man aber auch als Funktion implementieren.Sirius3 hat geschrieben: @Alfons Mittelmeyer: global sollte in keinem Programm vorkommen. Zumal das meiste davon unnütz ist.
So eine wish Methode kann man für belebige GUI Elemente verwenden, sie soll daher keineswegs nur ein Bestandteil dieser Labelframe_1-Klasse seinSirius3 hat geschrieben:Wenn Du schon eine Labelframe_1-Klasse hast, dann könntest Du sie auch nutzen.
Sorry, dass ich meine Zeit nicht damit vertat, den Code für die GUI zu schreiben, sondern den Code generierte mit automatisch generierten Namen und Schlüsselwortargumenten.Sirius3 hat geschrieben:Du hast immer noch diese unmöglich komplizierte Variante, Schlüsselwortargumente zu übergeben, dass man es nicht lesen möchte. So nichtsagende Namen wie Labelframe_1 sollte man auch nicht benutzen.
Ich denke, es ist gut, dem Anfänger das Prinzip zu zeigen, wie etwas funktioniert. Und unschön anzusehender Code ist da gar nicht einmal so schlecht, da der Anfänger es dann schöner machen will und selber machen will, anstatt einfach nur die Vorlage zu kopieren.Sirius3 hat geschrieben:Soetwas einem Anfänger zu zeigen, halte ich nicht für gut, das könnte jemand für brauchbar halten.
Und beim Schöner machen, kannst dann Du ihm helfen.
@Alfons Mittelmeyer: Du hast Den Code geschrieben, und deswegen sage ich es Dir. Wie soll jemand, der noch am Anfang steht, wissen wie es besser geht. Dass Dein GUI-Designer schrecklichen Code schreibt, hatten wir schon an anderer Stelle. Wenn man Code generiert, den man danach ändert, sollte der so lesbar sein, wie es eben geht, da es ja kein Problem für einen Code-Generierer ist, auch schöne Keyword-Argumente zu schreiben. Ansonsten ist der Code ja so simple, dass man dafür keinen Designer braucht.
Der selbe Code, nur ohne global, aber immer noch mit zu vielen festen Fenstergrößen und Positionen.
Der selbe Code, nur ohne global, aber immer noch mit zu vielen festen Fenstergrößen und Positionen.
Code: Alles auswählen
import tkinter as tk
class Mainframe(tk.LabelFrame):
def __init__(self,master,**kwargs):
tk.LabelFrame.__init__(self,master,**kwargs)
tk.Button(self, text='wish on', command=self.wish_on).place(y=243,x=50)
self.button_frame = ButtonFrame(self, width=200, text='Noch ein Fenster', bd=0, relief='flat', bg='#d9d93c', height=150)
self.button_frame.place(y=300, x=0)
def wish_on(self):
self.button_frame.wish(300,140,-1)
class ButtonFrame(tk.LabelFrame):
def __init__(self, master, **kwargs):
tk.LabelFrame.__init__(self, master, **kwargs)
tk.Button(self, text='wish off', command=self.wish_off).place(y=83,x=50)
def wish_off(self):
self.wish(140,300,1)
def wish(self, y0, yn, step):
def do_move(y):
y += step
self.place(y=y)
if y != yn:
self.after(3, do_move, y)
do_move(y0)
def main():
app = tk.Tk()
app.geometry("280x370")
mainframe = Mainframe(app, width=200, text='Screen', bd=0, relief='flat', bg='#d949d9', height=300)
mainframe.place(y=28, x=43)
app.mainloop()
if __name__ == '__main__':
main()
Genau. Weil der Anfaenger, der bis dato keine Ahnung davon hat, wie man etwas macht, urploetzlich nicht nur aufhoert Code zu kopieren (was er bis jetzt immer getan hat), sondern auch noch einen Sinn fuer Code-Aesthetik entwickelt - unabhaengig von Dingen, die man ihm zeigt.Alfons Mittelmeyer hat geschrieben:Ich denke, es ist gut, dem Anfänger das Prinzip zu zeigen, wie etwas funktioniert. Und unschön anzusehender Code ist da gar nicht einmal so schlecht, da der Anfänger es dann schöner machen will und selber machen will, anstatt einfach nur die Vorlage zu kopieren.
"Do as I say, not as I do" hat noch in keinem Kontext funktioniert. Gerade an den vielen Projekten und Codeschnipseln rund um den Pi sieht man, dass es keine Grenze nach unten gibt... aber fuer mich ist hier EOD. Ich bleibe bei meiner Einschaetzung, dass fuer eine moderne UI ein modernes UI-Framework notwendig ist.
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Also hier wird das Arbeitsverzeichnis schon wieder hergestellt, Dazu die Datei test.py in ein Unterverzeichnis subdir legen:BlackJack hat geschrieben:@Alfons Mittelmeyer: Python stellt gar nichts wieder her. Es wurde nichts ausserhalb des Prozesses verändert was wiederhergestellt werden müsste.
Code: Alles auswählen
import os
print("Workdir original:"+os.getcwd())
os.chdir(os.path.dirname(os.path.realpath(__file__)))
print("Workdir changed :"+os.getcwd())
python3 subdir/test.py
python3 subdir/test.py
Beim zweiten Mal läßt sich das auch aufrufen, und wenn man es zum zweiten Mal aufruft, werden dieselben Verzeichnisse angezeigt, wie beim ersten Aufruf. Nichts wurde also verstellt, bzw es wurde nach Beendigung des ersten Aufrufes wieder zurückgesetzt.
@Alfons Mittelmeyer: jeder Prozess hat sein eigenes Arbeitsverzeichnis. So dass wenn ein Prozess sein Verzeichnis verändert, hat das keine Auswirkung auf andere Prozesse. Du startest nacheinander zwei Prozesse, jedes startet mit dem ursprünglichen Pfad des aufrufenden Prozesses. Da wird wirklich nichts zurückgesetzt.
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Ja, beim Raspberry Pi, wahrscheinlich auch auf dem PC mit Linux, sind solche Animationen mit after sehr flüssig. Aber unter Windows ist dieses nicht der Fall - zumindest nicht mit meinem Windows7 Ultimate 32 Bit. Wenn man solche Animationen auch für Windows programmieren möchte, sollte man ein entsprechendes modernes UI-Framework verwenden,__deets__ hat geschrieben:Ich bleibe bei meiner Einschaetzung, dass fuer eine moderne UI ein modernes UI-Framework notwendig ist.
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Naja, jedenfalls sorgt python dafür, dass der aktuelle Pfad der Shell unverändert bleibt - ob durch Zurücksetzen oder durch Verwendung eines Prozesses ist an sich schnuppe.Sirius3 hat geschrieben:@Alfons Mittelmeyer: jeder Prozess hat sein eigenes Arbeitsverzeichnis. So dass wenn ein Prozess sein Verzeichnis verändert, hat das keine Auswirkung auf andere Prozesse. Du startest nacheinander zwei Prozesse, jedes startet mit dem ursprünglichen Pfad des aufrufenden Prozesses. Da wird wirklich nichts zurückgesetzt.
@Alfons Mittelmeyer: Python sorgt für gar nichts. Man kann nur sein eigenes Arbeitsverzeichnis ändern, nicht das eines anderen Prozesses, das geht gar nicht. Und dass ein Modul von sich aus den Pfad ändert ist einfach nur unerwartet, damit rechnet niemand und stell Dir zwei Module vor, die das machen, dann kann man die nicht zusammen benutzen. Daher ist es höchst unangebracht, das zu tun.
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
@Sirius3: Wichtig ist eine flexible Programmierung, das heißt, man soll allgemein verwendbare Funktionen auch allgemein verwenden können. Die wish-Funktion als Methode für ein einziges GUI Element zu definieren, sollte nicht sein.
Ein Anwendung kann wachsen und am Ende viele unterschiedliche Fenster haben, die mit wish verschoben werden. Daher ist die wish Funktion gesondert zu implementieren. Hier einmal nicht mit globalen Variablen:
Ein Anwendung kann wachsen und am Ende viele unterschiedliche Fenster haben, die mit wish verschoben werden. Daher ist die wish Funktion gesondert zu implementieren. Hier einmal nicht mit globalen Variablen:
Code: Alles auswählen
import tkinter as tk
# ---- Definition of wish function ---------------
def wish(element,y0, yn, step,timestep):
def do_move(y):
y += step
element.place(y=y)
if y != yn:
element.after(timestep, do_move, y)
do_move(y0)
# ---- GUI ---------------------------------------
class Mainframe(tk.LabelFrame):
def __init__(self,master,**kwargs):
tk.LabelFrame.__init__(self,master,**kwargs)
tk.Button(self, text='wish on', command=self.wish_on).place(y=243,x=50)
self.button_frame = ButtonFrame(self, width=200, text='Noch ein Fenster', bd=0, relief='flat', bg='#d9d93c', height=150)
self.button_frame.place(y=300, x=0)
def wish_on(self):
wish(self.button_frame,300,140,-1,3)
class ButtonFrame(tk.LabelFrame):
def __init__(self, master, **kwargs):
tk.LabelFrame.__init__(self, master, **kwargs)
tk.Button(self, text='wish off', command=self.wish_off).place(y=83,x=50)
def wish_off(self):
wish(self,140,300,1,3)
def main():
app = tk.Tk()
app.geometry("280x370")
mainframe = Mainframe(app, width=200, text='Screen', bd=0, relief='flat', bg='#d949d9', height=300)
mainframe.place(y=28, x=43)
app.mainloop()
if __name__ == '__main__':
main()
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Jedem wie es beliebt, wenn das Dich glücklicher macht:Sirius3 hat geschrieben:@Alfons Mittelmeyer: zum Wiederverwenden von Methoden hat man was ganz tolles erfunden: Objektorientierte Programmierung. Kannst Du Dir mal bei Gelegenheit anschauen.
Code: Alles auswählen
import tkinter as tk
# ---- Definition of wish class ---------------
class WishClass():
def wish(self,element,y0, yn, step,timestep):
def do_move(y):
y += step
element.place(y=y)
if y != yn:
element.after(timestep, do_move, y)
do_move(y0)
# ---- GUI ---------------------------------------
class Mainframe(tk.LabelFrame):
def __init__(self,master,**kwargs):
tk.LabelFrame.__init__(self,master,**kwargs)
tk.Button(self, text='wish on', command=self.wish_on).place(y=243,x=50)
self.button_frame = ButtonFrame(self, width=200, text='Noch ein Fenster', bd=0, relief='flat', bg='#d9d93c', height=150)
self.button_frame.place(y=300, x=0)
self.wish_object=WishClass()
def wish_on(self):
self.wish_object.wish(self.button_frame,300,140,-1,3)
class ButtonFrame(tk.LabelFrame):
def __init__(self, master, **kwargs):
tk.LabelFrame.__init__(self, master, **kwargs)
tk.Button(self, text='wish off', command=self.wish_off).place(y=83,x=50)
self.wish_object=WishClass()
def wish_off(self):
self.wish_object.wish(self,140,300,1,3)
def main():
app = tk.Tk()
app.geometry("280x370")
mainframe = Mainframe(app, width=200, text='Screen', bd=0, relief='flat', bg='#d949d9', height=300)
mainframe.place(y=28, x=43)
app.mainloop()
if __name__ == '__main__':
main()