I have a menu with items through which I want to open separate windows:
from tkinter import *
from PIL import ImageTk, Image
def show_text():
top = Toplevel()
top.title("Text")
top.geometry("200x100")
my_label = Label(top, text="Text")
my_label.pack()
def show_image():
global my_image
top = Toplevel()
top.title("Graph")
my_image = ImageTk.PhotoImage(Image.open("my_image.png"))
my_label = Label(top, image = my_image)
my_label.pack()
root = Tk()
root.title("Main window")
root.geometry("300x200")
my_menu = Menu(root)
root.config(menu=my_menu)
item_menu = Menu(my_menu)
my_menu.add_cascade(label="Info", menu=item_menu)
item_menu.add_command(label="Text", command=show_text)
item_menu.add_command(label="Graph", command=show_image)
root.mainloop()
The problem is that when I select an item from menu again I get another instance of window:
It's not a problem in case of windows with text, but in case of windows with picture when the new instance of window opens, the picture in the old instance of window disappear:
My questions:
If I want to allow to have multiple instances of windows, then how can I prevent pictures in old instances of windows from disappearing?
If I don't want to allow multiple instances of the same window, then how can I close old instance of window when create new (select menu item again)?
Maybe more prudent decision would be to disable menu item after it was chosen and enable again after the corresponding window is closed. How can this be done?
P.S. Instead of my_image.png in the code you can use any suitable image on your computer.
Question 1: If I want to allow to have multiple instances of windows, then how can I prevent pictures in old instances of windows from disappearing?
Your code does this. The previous windows' image don't disappear.
Quetion 2: If I don't want to allow multiple instances of the same window, then how can I close old instance of window when create new (select menu item again)?
Give different names for two toplevel windows say text_top
and image_top
. In the respective toplevel window functions, add a conditional statement as follows. Also make the toplevel widown global( add respective global declaration after importing tkinter which I've not mentioned here)
def show_text():
global text_top
if text_top.winfo_exists():
text_top.destroy()
text_top = Toplevel(root)
# Rest of the function
def show_image():
global image_top
if image_top.winfo_exists():
image_top.destroy()
image_top = Toplevel(root)
# Rest of the function
Question 3: Maybe more prudent decision would be to disable menu item after it was chosen and enable again after the corresponding window is closed. How can this be done?
See the following code. changes given as comments inside the code
from tkinter import *
from PIL import ImageTk, Image
def show_text():
# A function to enable text_widget while closing the toplevel window
def enable_text_menu():
item_menu.entryconfig(0, state = NORMAL) # 0 is index
top.destroy()
top = Toplevel()
top.title("Text")
top.geometry("200x100")
# to disable the menu item- syntax: item_menu.entryconfig(index, state=DISABLED)
item_menu.entryconfig(0, state = DISABLED)
my_label = Label(top, text="Text")
my_label.pack()
# the following line triggers the function enable_text_menu on closing Toplevel
top.protocol("WM_DELETE_WINDOW", enable_text_menu)
def show_image():
# A function to enable graph_widget while closing the toplevel window
def enable_image_menu():
item_menu.entryconfig(1, state=NORMAL) # 1 is index
top.destroy()
global my_image
top = Toplevel()
top.title("Graph")
# to disable the menu item- syntax: item_menu.entryconfig(index, state=DISABLED)
item_menu.entryconfig(1, state=DISABLED)
my_image = ImageTk.PhotoImage(Image.open("my_image.png"))
my_label = Label(top, image = my_image)
my_label.pack()
# the following line triggers the function enable_image_menu on closing Toplevel
top.protocol("WM_DELETE_WINDOW", enable_image_menu)
root = Tk()
root.title("Main window")
root.geometry("300x200")
my_menu = Menu(root)
root.config(menu=my_menu)
# In the following line, 'tearoff=0' for not including the dashed line on the top
item_menu = Menu(my_menu, tearoff=0)
my_menu.add_cascade(label="Info", menu=item_menu)
item_menu.add_command(label="Text", command=show_text)
item_menu.add_command(label="Graph", command=show_image)
root.mainloop()