Python Forum
[Tkinter] identify window
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tkinter] identify window
#1
Hi, i am in a spot of trouble trying to do this:
I want to create a number of (tkinter) windows dynamically and simultaneously (between 2 and 10).
Each window has a button, when pressed, destroys the window.
The purpose is a selection process, because the windows will show images of things the user must choose between.

In pinciple this is not so difficult, just repeat 10 times win1 ... win10:
win1 = Tk()
win1.title('image x')
geo = '1000x1000+0+0'
win1.geometry(geo)
Button(win1, text='Select', command =  WIN1).pack(side = BOTTOM) -> the "def WIN1:" has code win1.destroy and do some other stuff.
................
But in python country, you would want to do this more compact, in a loop !, like so:
winList = ['winA', 'winB', 'winC', 'winD', 'winE', 'winF', 'winG', 'winH', 'winI', 'winJ']
for item in winList:
    item = Tk()
    geo = '1000x1000+0+0'
    item.geometry(geo)
    Button(item, text = 'Delete',command= lambda: WIN(item)).pack(side = BOTTOM)
Here lies the problem, because i'm having trouble in the command parameter to point to one def clause, whilst identifying the window to delete.
Help?
Paul
Reply
#2
Please, on future posts, show enough of a snippet that it can be run.

count = Number of windows to create
** Note ** added as an edit - As written, requires f-string which is available in python 3.6 or newer.

You can dynamically name the windows as well save everything in a dynamically created list:
import tkinter as tk


class DynamicWindows:
    def __init__(self, parent):
        parent.title('Parent window')
        parent.geometry('300x300+500+500')
        self.startx = 10
        self.starty = 10
        self.all_windows = []
    
    def add_window(self, name):
        index = len(self.all_windows)
        self.all_windows.append(tk.Toplevel())
        self.all_windows[index].title(name)
        geo = f'300x300+{self.startx}+{self.starty}'
        self.all_windows[index].geometry(geo)
        btn = tk.Button(self.all_windows[index], text='Destroy me', command = lambda: self.kill_me(index))
        btn.pack()
        # button = Tk.Button(master=frame, text='press', command= lambda: action(someNumber))
        self.startx += 20
        self.starty += 20

    def kill_me(self, index):
        self.all_windows[index].destroy()


def main():
    # add some windows
    root = tk.Tk()
    dw = DynamicWindows(root)
    count = 4
    winname = 'A'
    while count:
        dw.add_window(f'win{winname}')
        print(f'winname: {winname}')
        winname = chr(ord(winname) + 1)
        count -= 1
    root.mainloop()


if __name__ == '__main__':
    main()
Reply
#3
And it is not necessary to store the Toplevel IDs in a list in this case as you can just send the ID to the destroy function
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
        tk.Button(self.root, text="Open a Toplevel",
                  command=self.open_another).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_top):
        id_top.destroy()

    def open_another(self):
        self.button_ctr += 1
        id_top = tk.Toplevel(self.root)
        tk.Label(id_top, text="Toplevel #%d \n Two line display" % (self.button_ctr)
                ).grid()
        tk.Button(id_top, text="Close Toplevel #%d" % (self.button_ctr),
                  command=partial(self.close_it, id_top),
                  bg="orange", width=20).grid(row=1, column=0)

Ot=OpenToplevels()  
Reply
#4
2 great solutions, where i can filter out what i couldn't get done :
identify the windows when created in a loop. Thanks.
Both solutions do seem to involve a master window, that, when destroyed, takes all others along.
My "simpler" solution does not do that, so i'll have to marry the best of both worlds.

After 45 years of coding in different languages, i admire the marketing guy who got away with saying that python
is more "readable" than other languages. If one thing, it improves your qualities as a detective. :-)

Paul
Reply
#5
for master window use withdraw, not destroy.
You will have to capture exit so that you can manually destroy at end
for example, my code add line 11:
import tkinter as tk

class DynamicWindows:
    def __init__(self, parent):
        parent.title('Parent window')
        parent.geometry('300x300+500+500')
        self.startx = 10
        self.starty = 10
        self.all_windows = []
        parent.withdraw()
see: http://effbot.org/zone/tkinter-window-destroy.htm for destroy
Reply
#6
OK, i have used "withdraw" before, when i want to show a "tkinter filedialog"
without going through the trouble of designing fancy parent windows.

It's clever to use it in this situation, it 'll save me coding time.
thx,
Paul
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  tkinter window and turtle window error 1885 3 3,282 Nov-02-2019, 12:18 PM
Last Post: 1885
  update a variable in parent window after closing its toplevel window gray 5 5,703 Mar-20-2017, 10:35 PM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020