how to use tkinter button as a method [duplicate] - python

This question already has answers here:
Why is my Button's command executed immediately when I create the Button, and not when I click it? [duplicate]
(5 answers)
Closed 5 months ago.
I want to use a tkinter button as a method but the function the button is meant to call runs immediately after starting the program and does not run subsequently.
import tkinter as tk
class Button():
def __init__(self,window):
self.window = window
def add_button(self, func):
tk.Button(self.window, text='print', command=func).pack()
def do_something(the_thing):
print(f'{the_thing}')
return
root = tk.Tk()
button_o = Button(root)
button_o.add_button(do_something(the_thing='ook'))
root.mainloop()

You can use lambda function here
import tkinter as tk
class Button():
def __init__(self,window):
self.window = window
def add_button(self, func):
tk.Button(self.window, text='print', command=func).pack()
def do_something(the_thing):
print(f'{the_thing}')
return
root = tk.Tk()
button_o = Button(root)
button_o.add_button(lambda:do_something(the_thing='ook'))
root.mainloop()

just realized i could decorate the function.
import tkinter as tk
class Button():
def __init__(self,window):
self.window = window
def add_button(self, func):
tk.Button(self.window, text='print', command=func).pack()
def decorator(the_thing):
def do_something():
print(f'{the_thing}')
return do_something
root = tk.Tk()
button_o = Button(root)
button_o.add_button(decorator(the_thing='ook'))
root.mainloop()

Related

Tkinter - The Root Window hides itself after close its Toplevel window

below my code:
from tkinter import *
from tkinter import ttk
class MainWindow:
def __init__(self):
self.parent=Tk()
self.parent.geometry("494x410+370+100")
self.parent.title("My Software - TEST")
self.parent.iconbitmap("icon.ico")
Button = ttk.Button(self.parent, text="open a new widnow", command=self.OpenNewWindow)
Button.place(x=16, y=16)
def OpenNewWindow(self):
self.obj = NewWindow(self)
class NewWindow:
def __init__(self, mw):
self.window, self.mw = Toplevel(mw.parent), mw
self.window.geometry("200x150+360+200")
self.window.title("New Window")
self.window.iconbitmap("icon.ico")
# the "try/except" code has an issue..
try:
self.window.focus()
self.mw.parent.attributes('-disabled', 1)
self.window.transient(mw.parent)
self.window.grab_set()
self.mw.parent.wait_window(self.window)
finally:
self.mw.parent.attributes('-disabled', 0)
def main():
app=MainWindow()
if __name__=="__main__":
main()
the try/except code makes the Toplevel window important. when it runs, the user can't touch the root window, and if he try to do it, a bell songs and the Toplevel window flashes. it's the exactly behaivour that I want! but this piece of code has an issue.. when the user close the Toplevel window, the root doesn't became the active window. it's a big issue because it makes the root window to go back the other ones. see my gif to understand better what I mean:
http://www.imagebam.com/image/c983ce1356199964
how can I solve this issue?
You've got the wrong idea about try ... finally; it does not work that way. There are 2 ways to do what you want. One way is to simply put that code in the main window:
from tkinter import *
from tkinter import ttk
class MainWindow:
def __init__(self):
self.parent=Tk()
self.parent.geometry("494x410+370+100")
self.parent.title("My Software - TEST")
self.parent.iconbitmap("icon.ico")
Button = ttk.Button(self.parent, text="open a new widnow", command=self.OpenNewWindow)
Button.place(x=16, y=16)
def OpenNewWindow(self):
self.parent.attributes('-disabled', 1)
self.obj = NewWindow(self)
self.parent.attributes('-disabled', 0)
class NewWindow:
def __init__(self, mw):
self.window, self.mw = Toplevel(mw.parent), mw
self.window.geometry("200x150+360+200")
self.window.title("New Window")
self.window.iconbitmap("icon.ico")
self.window.focus()
self.window.transient(mw.parent)
self.window.grab_set()
self.mw.parent.wait_window(self.window)
def main():
app=MainWindow()
app.parent.mainloop()
if __name__=="__main__":
main()
Another way is to make a method to run when the toplevel closes:
from tkinter import *
from tkinter import ttk
class MainWindow:
def __init__(self):
self.parent=Tk()
self.parent.geometry("494x410+370+100")
self.parent.title("My Software - TEST")
self.parent.iconbitmap("icon.ico")
Button = ttk.Button(self.parent, text="open a new widnow", command=self.OpenNewWindow)
Button.place(x=16, y=16)
def OpenNewWindow(self):
self.obj = NewWindow(self)
class NewWindow:
def __init__(self, mw):
self.window, self.mw = Toplevel(mw.parent), mw
self.window.geometry("200x150+360+200")
self.window.title("New Window")
self.window.iconbitmap("icon.ico")
self.window.protocol("WM_DELETE_WINDOW", self.on_close)
self.window.focus()
self.mw.parent.attributes('-disabled', 1)
self.window.transient(mw.parent)
self.window.grab_set()
self.mw.parent.wait_window(self.window)
def on_close(self):
self.mw.parent.attributes('-disabled', 0)
self.window.destroy()
def main():
app=MainWindow()
app.parent.mainloop()
if __name__=="__main__":
main()

how to import the another tkinter python class code to open the new tkinter window?

I have two tkinter class1.py and class2.py. I face the problem that when i import the class2.py in class1.py it executes the class2.py first then only execute class1.py.
###class 1.py
import tkinter as tk
import class2
from class2 import root2
class MyApp1(object):
def __init__(self, parent):
self.root1 = parent
self.root1.title("Main frame")
self.frame = tk.Frame(parent)
self.frame.pack()
btn = tk.Button(self.frame, text="Open Frame", command=)
btn.pack()
def call(self):
self.root1.withdraw()
x = class2.MyApp2(root2)
root1 = tk.Tk()
root1.geometry("800x600")
app = MyApp1(root1)
root1.mainloop()
###class2.py
import tkinter as tk
class MyApp2(object):
def __init__(self, parent):
self.root2 = parent
self.root2.title("Main frame")
self.frame = tk.Frame(parent)
self.frame.pack()
btn = tk.Button(self.frame, text="Open Frame", command=self.openFrame)
btn.pack()
def openFrame(self):
pass
root2 = tk.Tk()
root2.geometry("800x600")
#app = MyApp2(root2)
root2.mainloop()
Now How can I import the class2.py from the class1.py and outcome becomes class1 tkinter window then only class2 tkinter window?
You should not be importing code like this. The proper way to make your code importable is to make sure it only has functions and class definitions. Then, the code that does the importing is responsible for calling the functions and instantiating the classes.
class2.py should look something like this:
import tkinter as tk
class MyApp2(object):
def __init__(self, parent):
self.root2 = parent
self.root2.title("Main frame")
self.frame = tk.Frame(parent)
self.frame.pack()
btn = tk.Button(self.frame, text="Open Frame", command=self.openFrame)
btn.pack()
def openFrame(self):
pass
class1.py can now safely import this file. It can then create the instance of MyApp2 like this:
def call(self):
self.root1.withdraw()
new_window = tk.Toplevel()
class2.MyApp2(new_window)
Or, if you no longer need the main window, you can destroy everything inside the main window and then reuse it for the new class:
def call(self):
for child in self.root1.winfo_children():
child.destroy()
class2.MyApp2(self.root1)

How to implement listener using tkinter?

I am trying to develop a dialog box to be used with tkinter that has an entry box and a button. I want to be able to enter a value in the entry box and have the entered value "returned" when the dialog is destroyed. The following code works, but does not perform as I've described. There are two buttons on the gui. The first launches the dialog box and the second retrieves the entered value. I wish to eliminate the second button and have a listener activate the getValues method when the "Save Input" button in the dialog is pressed. Here is the code:
from tkinter import *
class myDialog():
def __init__(self):
self.t = Toplevel()
self.t.title("Sample")
self.answer = None
self.v1 = StringVar()
self.e1 = Entry(self.t, textvariable=self.v1)
self.e1.focus()
self.e1.pack()
self.saveButton = Button(self.t, text="Save Input", command=self.buttonPressed)
self.saveButton.pack()
def buttonPressed(self):
print("Popup Button Pressed")
self.answer = self.e1.get()
self.t.destroy()
class myTk(Tk):
def __init__(self):
Tk.__init__(self)
self.button = Button(text="Display Dialog", command = self.displayPopButton)
self.button.pack()
self.getButton = Button(text="Print Values", command=self.getValues)
self.getButton.pack()
def displayPopButton(self):
self.b1 = myDialog()
def getValues(self):
print(self.b1.answer)
myTk().mainloop()
You could be passing in your main object as a param in your Dialog, and call the master method within the buttonPressed method:
class myDialog():
def __init__(self, master):
self.t = Toplevel()
self.master = master
# ... #
def buttonPressed(self):
print("Popup Button Pressed")
self.answer = self.e1.get()
self.master.getValues()
self.t.destroy()
class myTk(Tk):
# ... #
def displayPopButton(self):
self.b1 = myDialog(self)
This achieves what you want, but personally I don't think it's good OOP. It makes your Dialog reliant on having the expected master type and the required method. You could organize it a little differently to be more explicit::
class myDialog():
def __init__(self, func_to_call):
self.t = Toplevel()
self.btn_func = func_to_call
# ... #
def buttonPressed(self):
print("Popup Button Pressed")
self.answer = self.e1.get()
func_to_call()
self.t.destroy()
class myTk(Tk):
# ... #
def displayPopButton(self):
self.b1 = myDialog(self.getValues)
In any case, I would at least subclass myDialog as a Toplevel. And perhaps rethink how I want the objects to refer to each other.
You can make myDialog a modal dialog using grab_set() and wait_window():
from tkinter import *
class myDialog():
def __init__(self):
self.t = Toplevel()
self.t.title("Sample")
self.answer = None
self.v1 = StringVar()
self.e1 = Entry(self.t, textvariable=self.v1)
self.e1.focus()
self.e1.pack()
self.saveButton = Button(self.t, text="Save Input", command=self.buttonPressed)
self.saveButton.pack()
# handle user clicking the 'x' button at the title bar
self.t.protocol('WM_DELETE_WINDOW', self.buttonPressed)
def buttonPressed(self):
print("Popup Button Pressed")
self.answer = self.e1.get()
self.t.destroy()
def show(self):
# make the toplevel act like a modal dialog
self.t.grab_set()
self.t.wait_window(self.t)
# return the answer when the toplevel is closed/destroyed
return self.answer
class myTk(Tk):
def __init__(self):
Tk.__init__(self)
self.button = Button(text="Display Dialog", command = self.displayPopButton)
self.button.pack()
def displayPopButton(self):
self.b1 = myDialog().show()
print(self.b1)
myTk().mainloop()

How to close the whole GUI when toplevel is closed tkinter

I'm writing a tkinter app that creates a class with multiple toplevels. I need to be able to close the whole gui when any of the X button in the toplevels are pressed. How can I do this?
def main():
root = tk.Tk()
app = Example(master=root)
app.mainloop()
class Example(tk.Frame):
def __init__(self, master):
self.master = master
super().__init__(master)
self.initUI()
def initUI(self):
self.master.withdraw()
self.initUIL = tk.Toplevel(self.master)
self.initUIL.title('Init')
self.pack(fill = tk.BOTH, expand=1)
frame1 = tk.Frame(self.initUIL)
#I need to close the whole gui when the x in this toplevel is pressed
I solved it, it was pretty easy, you need to change the protocol for each toplevel.
self.toplevel.protocol("WM_DELETE_WINDOW", self.ask_quit)
def ask_quit():
MsgBox = tk.messagebox.askquestion ('Quit',"Are you sure you want to quit?")
if MsgBox == 'yes':
self.master.destroy()

tkinter quit crash

I am very new to Tkinter. I made this "Hello World"-like GUI program in Tkinter. However, every time I click on the quit button, the program crashes. Thanks in advance!
from Tkinter import *
import sys
class Application(Frame):
def __init__(self,master=None):
Frame.__init__(self,master=None)
self.grid()
self.createWidgets()
def createWidgets(self):
self.quitButton = Button(text='Quit',command=self.quit)#Problem here
self.quitButton.grid()
app = Application()
app.master.title("Sample application")
app.mainloop()
In Tkinter the root element is a Tk object. Application should be a subclass of Tk, not Frame:
from Tkinter import *
import sys
class Application(Tk):
def __init__(self):
Tk.__init__(self)
self.grid()
self.createWidgets()
def createWidgets(self):
self.quitButton = Button(text='Quit',command=self.destroy) # Use destroy instead of quit
self.quitButton.grid()
app = Application()
app.title("Sample application")
app.mainloop()
This Code works fine now:
import tkinter
class MyApp(tkinter.LabelFrame):
def __init__(self, master=None):
super().__init__(master, text="Hallo")
self.pack(expand=1, fill="both")
self.createWidgets()
self.createBindings()
def createWidgets(self):
self.label = tkinter.Label(self)
self.label.pack()
self.label["text"] = "Bitte sende ein Event"
self.entry = tkinter.Entry(self)
self.entry.pack()
self.ok = tkinter.Button(self)
self.ok.pack()
self.ok["text"] = "Beenden"
self.ok["command"] = self.master.destroy
def createBindings(self):
self.entry.bind("Entenhausen", self.eventEntenhausen)
self.entry.bind("<ButtonPress-1>", self.eventMouseClick)
self.entry.bind("<MouseWheel>", self.eventMouseWheel)
def eventEntenhausen(self, event):
self.label["text"] = "Sie kennen das geheime Passwort!"
def eventMouseClick(self, event):
self.label["text"] = "Mausklick an Position " \
"({},{})".format(event.x, event.y)
def eventMouseWheel(self, event):
if event.delta < 0:
self.label["text"] = "Bitte bewegen Sie das Mausrad"\
" in die richtige Richtung."
else:
self.label["text"] = "Vielen Dank!"
root = tkinter.Tk()
app = MyApp(root)
app.mainloop()
When you use self.quit() the python interpreter closes down without the tkinter application bieng closed . So try .destroy() command and after .mainloop() use sys.quit(). Hope this helps.
Your using __init__ difficultly. Do this:
from tkinter import *
root = Tk()
btn_quit = Button(root, text='Quit', command=quit()).pack()
root.mainloop()
If you do self.quit, that is the quit command so the thing will crash!
Hope this helps!
try using raise SystemExit
this may be better.
or check out me

Categories

Resources