Why do I get an extra empty window in Tkinter? - python

Here is my code:
from tkinter import *
OPTIONS = ["Available","Busy","Invisible","Away"]
now = Toplevel()
variable = StringVar(now)
variable.set(OPTIONS[0]) # default value
details = {"U_status":""}
def verify():
global u_status
details["U_status"]=variable.get()
print ("value is:" + variable.get())
now.destroy()
def status():
w = OptionMenu(now, variable, *OPTIONS)
w.pack()
button = Button(now, text="OK", command=verify, relief='flat')
button.pack()
if __name__=='__main__':
status()
mainloop()
While running the above code, along with the window (I wanted) another empty window appears. Can anyone figure out what is wrong in this code?

Here now = Toplevel() should be replaced with Tk(), like:
now = Tk()
When you use Toplevel() a Tk() window is made in the background, if its not already made(your case), and that is the reason you are getting a blank new window. Actually that blank window is your main window.
Toplevel() is used to make child windows for the parent Tk() windows,ie, if you want sub windows within your main window(now), you will use Toplevel(). Because more than one Tk() in your code will cause some errors later on.

The blank window is actually the root window of your app that tkinter creates by default. You probably want to be explicit, and create a tk.Tk() root, and keep a reference to it.
New windows can be spawned and destroyed at leisure; your app will continue to exist as long as you keep the root active.
Maybe something like this:
import tkinter as tk
def verify():
now = tk.Toplevel(root)
details["U_status"] = variable.get()
txt = f'value is: {details["U_status"]}'
tk.Label(now, text=txt).pack()
now.after(3000, now.destroy)
def status():
tk.OptionMenu(root, variable, *OPTIONS).pack()
tk.Button(root, text="OK", command=verify, relief='flat').pack()
if __name__=='__main__':
OPTIONS = ["Available", "Busy", "Invisible", "Away"]
root = tk.Tk()
variable = tk.StringVar(root)
variable.set(OPTIONS[0])
details = {"U_status": ""}
status()
root.mainloop()

Related

python child Tk window

I have a code where I have a drop down menu and what I need to do is that when I select an entry from the drop down list (ex: Send an email) and press on go, I need this to populate another tk window (child window).
I know I am doing something wrong but can not comprehend how to overcome this, I have been searching for a while but I am unable to find a solution or guidance on how to complete this.
Thanks in advance for your help with this!
from tkinter import *
root = Tk()
root.geometry("400x100")
#========================================
#Entry area to enter the number
labelmain = Label(root,text="Please enter number:")
labelmain.pack()
entryvar = StringVar(root)
entrymain = Entry(root, textvariable=entryvar,width=30)
entrymain.pack()
#========================================
#Create option drop down list:
lst = ["Save details to DB", "Send an email", "Copy format", "email", "View report"]
ddl = StringVar(root)
ddl.set(lst[0])
option = OptionMenu(root, ddl, *lst)
option.pack()
#========================================
#Function to get the values from drop down list
def ok():
print("value is: " + ddl.get())
#root.quit()
#=========================================
#Button to process the selection:
btnmain = Button(root,text="Go", command=ok)
btnmain.pack()
#=========================================
if ddl.get() == "Send an email":
samepmrdb = Tk()
samepmrdb.mainloop()
root.mainloop()
You are checking the value of ddl right after you open up your window. As you said in your question, you want some stuff happen after pressing the button so you need to put those codes under the command of said button.
Also, a tkinter app should only have one Tk() instance and one mainloop. When you want to open another window, you should use Toplevel().
def ok():
print("value is: " + ddl.get())
if ddl.get() == "Send an email":
samepmrdb = Toplevel()
#now you can populate samepmrdb as you like
If all you're looking to do is find a way to update a second tkinter window with the selection from an OptionMenu on the first tkinter window this can be achieved easily using the below code:
from tkinter import *
class App:
def __init__(self, master):
self.master = master
self.top = Toplevel(master)
self.master.withdraw()
self.var = StringVar()
self.var.set("Example1")
self.option = OptionMenu(self.top, self.var, "Example1", "Example2", "Example3", "Example4")
self.button = Button(self.top, text="Ok", command=lambda:self.command(self.var))
self.label = Label(self.master)
self.option.pack()
self.button.pack()
self.label.pack()
def command(self, var):
self.master.deiconify()
self.label.configure(text=var.get())
self.label.pack()
root = Tk()
app = App(root)
root.mainloop()
This creates a Toplevel widget which contains an OptionMenu and Button widget. The Button widget will then output the selection from the OptionMenu widget when pressed.
This kind of logic can be used for all sorts of things and it's relatively simple to pass information from one window to another, provided this is what your question is asking.

Problems with 2 different GUI windows

So my first GUI window is meant for taking input from user :
from tkinter import *
from main import *
root = Tk()
root.configure(background="orange")
root.wm_title("Python Project")
label_1 = Label(root, text="Project Name",bg="orange",fg="black")
label_2 = Label(root, text="Site URL Link",bg="orange",fg="black")
entry_1 = Entry(root)
entry_2 = Entry(root)
label_1.grid(row=0,sticky=W)
label_2.grid(row=3333,sticky=W)
entry_1.grid(row=0,column=1,padx=50,ipadx=100)
entry_2.grid(row=3333,column=1,ipadx=100)
def callback():
a1 = entry_1.get()
a2 = entry_2.get()
mmm(a1,a2,root) # main program
button1 = Button(root,text="Run",command=callback)
button2=Button(root,text="Quit",command=root.quit)
button1.grid(row=3334,ipadx=15,padx=50,column=1)
button2.grid(row=3335,column=1,ipadx=15,padx=50)
root.mainloop()
And then i use another GUI window someone in this forum made to show my results :
from tkinter import *
root = Tk()
textbox = Text(root)
textbox.pack()
def redirector(inputStr):
textbox.insert(INSERT, inputStr)
sys.stdout.write = redirector # whenever sys.stdout.write is called, redirector is called.
sys.stderr.write = redirector
root.mainloop()
Now every time i run the first GUI , both GUIs open although there is no way the code reached the second GUI code yet... What is the problem here?
Also the second GUI is supposed to print from a class , but i have a bunch of error when I try to just put it there . What changes I need to make so I can make this 2nd GUI work with a class?

How do you close a tkinter window in another function?

I want a button in my window to open a new window and close the previous one. Is it possible to have one button do both of these? I've tried in the following code, but it hasn't worked, just told me that window is not defined:
import tkinter
def window1():
window = tkinter.Tk()
tkinter.Button(window, text = "Next", command = window2).pack()
window.mainloop()
def window2():
window.destroy() #This is where the error is
menu = tkinter.Tk()
etc, etc, etc
window1()
First, you need to return the window object from the first function:
def window1():
window = tkinter.Tk()
tkinter.Button(window, text = "Next", command = lambda: window2(window)).pack()
window.mainloop()
return window
Then, you need to pass the window as an argument to your function:
def window2(window):
window.destroy()
menu = tkinter.Tk()
And then call window1 with:
window = window1()
and click the button to destroy it and do the rest
This is an example using Toplevels, which is usually a better choice than creating, destroying, re-creating Tk() instances. The unique Toplevel ID is passed to the close_it function using partial(). You would, of course, combine them or have the close function call the open function.
try:
import Tkinter as tk ## Python 2.x
except ImportError:
import tkinter as tk ## Python 3.x
from functools import partial
class OpenToplevels():
""" open and close additional Toplevels with a button
"""
def __init__(self):
self.root = tk.Tk()
self.button_ctr=0
but=tk.Button(self.root, text="Open a Toplevel",
command=self.open_another)
but.grid(row=0, column=0)
tk.Button(self.root, text="Exit Tkinter", bg="red",
command=self.root.quit).grid(row=1, column=0, sticky="we")
self.root.mainloop()
def close_it(self, id):
id.destroy()
def open_another(self):
self.button_ctr += 1
id = tk.Toplevel(self.root)
id.title("Toplevel #%d" % (self.button_ctr))
tk.Button(id, text="Close Toplevel #%d" % (self.button_ctr),
command=partial(self.close_it, id),
bg="orange", width=20).grid(row=1, column=0)
Ot=OpenToplevels()
Yes. Is possible. But you'll need to def that:
def window1:
blablabla
blablabla
def window2:
window2.destroy() <-- Here where the error was
How you noticed, put your name of window what you want Destroy and it will work!
using Python3
You could use a "global" such as:
root = Tk()
root.title('This is the root window')
def window_create():
global window_one
window_one = Tk()
window_one.title('This is window 1')
Then, from any function (or elsewhere) when you want to destroy window_one, do:
def window_destroyer():
window_one.destroy()
You could call your window_destroyer function from a button anywhere such as root which the example shows:
kill_window_btn = Button(root, text="Destroy", command=window_destroyer).pack()
Of course, follow your own naming conventions. :)
It seems to me, just 'global window_one' would solve it.

How do I get the Entry's value in tkinter?

I'm trying to use Tkinter's Entry widget. I can't get it to do something very basic: return the entered value. Does anyone have any idea why such a simple script would not return anything? I've tried tons of combinations and looked at different ideas.
This script runs but does not print the entry:
from Tkinter import *
root = Tk()
E1 = Entry(root)
E1.pack()
entry = E1.get()
root.mainloop()
print "Entered text:", entry
Seems so simple.
Edit
In case anyone else comes across this problem and doesn't understand, here is what ended up working for me. I added a button to the entry window. The button's command closes the window and does the get() function:
from Tkinter import *
def close_window():
global entry
entry = E.get()
root.destroy()
root = Tk()
E = tk.Entry(root)
E.pack(anchor = CENTER)
B = Button(root, text = "OK", command = close_window)
B.pack(anchor = S)
root.mainloop()
And that returned the desired value.
Your first problem is that the call to get in entry = E1.get() happens even before your program starts, so clearly entry will point to some empty string.
Your eventual second problem is that the text would anyhow be printed only after the mainloop finishes, i.e. you close the tkinter application.
If you want to print the contents of your Entry widget while your program is running, you need to schedule a callback. For example, you can listen to the pressing of the <Return> key as follows
import Tkinter as tk
def on_change(e):
print e.widget.get()
root = tk.Tk()
e = tk.Entry(root)
e.pack()
# Calling on_change when you press the return key
e.bind("<Return>", on_change)
root.mainloop()
from tkinter import *
import tkinter as tk
root =tk.Tk()
mystring =tk.StringVar(root)
def getvalue():
print(mystring.get())
e1 = Entry(root,textvariable = mystring,width=100,fg="blue",bd=3,selectbackground='violet').pack()
button1 = tk.Button(root,
text='Submit',
fg='White',
bg= 'dark green',height = 1, width = 10,command=getvalue).pack()
root.mainloop()

Multiple windows open at once in python

I've searched and found a few things on parent windows in python but that is not what I was looking for. I am trying make a simple program that opens a window and another window after that when the previous one is closed. I was also trying to implement some kind of loop or sleep time to destroy the window by default if the user does not. This is what I have (I'm new please don't laugh)
from tkinter import *
import time
root = Tk()
i = 0
if i < 1:
root.title("title")
logo = PhotoImage(file="burger.gif")
w1 = Label(root, image=logo).pack()
time.sleep(3)
root.destroy()
i = i + 1
if i == 1:
root.title("title")
photoTwo = PhotoImage(file="freedom.gif")
labelTwo = Label(root, image=photoTwo).pack()
time.sleep(3)
root.destroy()
i = i + 1
mainloop.()
Perhaps you're looking for something like this:
from tkinter import *
import time
def openNewWindow():
firstWindow.destroy()
secondWindow = Tk()
secondWindow.title("Second Window")
photoTwo = PhotoImage(file="freedom.gif")
labelTwo = Label(secondWindow, image=photoTwo).pack()
secondWindow.mainloop()
firstWindow = Tk()
firstWindow.title("First Window")
logo = PhotoImage(file="burger.gif")
w1 = Label(firstWindow, image=logo).pack()
closeBttn = Button(firstWindow, text="Close!", command=openNewWindow)
closeBttn.pack()
firstWindow.mainloop()
This creates a button in the first window, which the user clicks. This then calls the openNewWindow function, which destroys that window, and opens the second window. I'm not sure there's a way to do this using the window exit button.
To get create a more sustainable window creation, use this:
from tkinter import *
import time
def openThirdWindow(previouswindow):
previouswindow.destroy()
thirdWindow = Tk()
thirdWindow.title("Third Window")
photoTwo = PhotoImage(file="freedom.gif")
labelTwo = Label(thirdWindow, image=photoTwo).pack()
thirdWindow.mainloop()
def openSecondWindow(previouswindow):
previouswindow.destroy()
secondWindow = Tk()
secondWindow.title("Second Window")
photoTwo = PhotoImage(file="freedom.gif")
labelTwo = Label(secondWindow, image=photoTwo).pack()
closeBttn = Button(secondWindow, text="Close!", command= lambda: openThirdWindow(secondWindow))
closeBttn.pack()
secondWindow.mainloop()
def openFirstWindow():
firstWindow = Tk()
firstWindow.title("First Window")
logo = PhotoImage(file="burger.gif")
w1 = Label(firstWindow, image=logo).pack()
closeBttn = Button(firstWindow, text="Close!", command= lambda: openSecondWindow(firstWindow))
closeBttn.pack()
firstWindow.mainloop()
openFirstWindow()
This places the opening of each window in a seperate function, and passes the name of the window through the button presses into the next function. Another method would be setting the window names as global, but this is messy.
The function "lambda:" calls the function, in tkinter you must type this if you want to pass something through a command.
We initiate the whole process first first called "openFirstWindow()"

Categories