0

So I'm trying to create a program which uses multiple tk.Toplevel windows. The problem with this is, that all windows show up seperated as their "own App", so when you alt tab, you switch between the toplevel windows. The pseudocode would look something like this: import tkinter as tk

top_levels = {}

def open_toplevel():
    top_level = tk.Toplevel(root)
    top_level.geometry("300x200+0+0")
    top_levels.update({f"toplevel{len(top_levels.keys())}" : top_level})

root = tk.Tk()

button = tk.Button(root, command= open_toplevel)
button.place(x=0, y=0)

root.mainloop()

So my question, is: is there a way to unify them into "one window"?

  • You might want to [look at this accepted answer](https://stackoverflow.com/questions/7546050/switch-between-two-frames-in-tkinter). It is one way you could achieve what you want. – Rory Sep 02 '22 at 17:19

1 Answers1

1

If you want all of them to unify into one window then tk.Frame is a better widget to use instead of tk.Toplevel

The purpose of tk.Toplevel is to create a new temporary window, not an extra part of the window. But frames are a really good way to organise stuff.

This code below creates new frame every time you click the button. This is just a simple example. You can also use grid for widgets in a frame. I also put a border so you can see where the frames are located.

from tkinter import *

def open_frame():
    frame = Frame(root, highlightbackground="black", highlightthickness=2)
    lbl1 = Label(frame, text=f"Frame {len(frames) + 1} label 1")
    lbl2 = Label(frame, text=f"Frame {len(frames) + 1} label 2")
    lbl1.pack()
    lbl2.pack()
    frame.pack(padx=5, pady=5)
    frames.append(frame)


root = Tk()

frames = []

btn = Button(root, text="Open Frame", command=open_frame)
btn.pack()

root.mainloop()

I hope this solution is helpful

EDIT

Use this code here to move the frames:

from tkinter import *

def open_frame():
    global frame, frames
    frame = Frame(root, highlightbackground="black", highlightthickness=2)
    lbl1 = Label(frame, text=f"Frame {len(frames) + 1} label 1")
    lbl2 = Label(frame, text=f"Frame {len(frames) + 1} label 2")
    lbl1.pack()
    lbl2.pack()
    frame.pack(padx=5, pady=5)
    frame_number = len(frames)

    lbl1.bind('<B1-Motion>', lambda event: MoveWindow(event, frame_number))
    lbl2.bind('<B1-Motion>', lambda event: MoveWindow(event, frame_number))
    frame.bind('<B1-Motion>', lambda event: MoveWindow(event, frame_number))
    
    frames.append(frame)
    labels.append(lbl1)
    labels.append(lbl2)

def MoveWindow(event, frame_number):
    global root, frames
    root.update_idletasks()
    f = frames[frame_number]
    x = f.winfo_width()/2
    y = f.winfo_height()*1.5
    f.place(x=event.x_root-x, y=event.y_root-y)

root = Tk()
root.geometry("500x500")

frames = []
labels = []

btn = Button(root, text="Open Frame", command=open_frame)
btn.pack()

root.mainloop()
ss3387
  • 299
  • 3
  • 19
  • I had done it with frames before, but the main problem I encountered was that I want the windows/frames to move, when I implement this the frames always lag behind, but maybe I'll have to try this out. Thx for the answer! – DarkLSD_GuY Sep 02 '22 at 18:34
  • If you want your frame to move then you can actually bind them with B1 -Motion – ss3387 Sep 04 '22 at 15:54
  • You can now see the edit I have done in my answer. It allows you to move frames. Those numbers that I used to place the frame are irrelevant. I just used those because the mouse pointer doesn't feel centred to the frame when you are moving it. – ss3387 Sep 04 '22 at 16:23