Tkinter Toplevel inf different file/function - python

I am trying to create a Toplevel window, however, this Toplevel is called from a different file in the same directory within a function.
Apologies I am by no means a tkinter or python guru. Here are the two parts of the code. (snippets)
#File 1 (Main)
import tkinter as tk
from tkinter import *
import comm1
from comm1 import com1
root = tk.Tk()
root.title("")
root.geometry("1900x1314")
#grid Center && 3x6 configuration for correct gui layout
root.grid_rowconfigure(0, weight=1)
root.grid_rowconfigure(11, weight=1)
root.grid_columnconfigure(0, weight=1)
root.grid_columnconfigure(11, weight=1)
#background image
canvas = Canvas(root, width=1900, height=1314)
canvas.place(x=0, y=0, relwidth=1, relheight=1)
bckground = PhotoImage(file='img.png')
canvas.create_image(20 ,20 ,anchor=NW, image=bckground)
#command to create new Toplevel
btn1 = tk.Button(root, text='Top', command=com1, justify='center', font=("Arial", 10))
btn1.config(anchor=CENTER)
btn1.grid(row=4, column=1)
#File 2 (Toplevel)
#command for new window
def com1():
newWindow1 = Toplevel(root)
newWindow1.title("")
newWindow1.geometry("500x500")
entry1 = tk.Entry(root, justify='center' , font=("Arial", 12), fg="Grey")
newWindow1.pack()
newWindow1.mainloop()
The weird part is this worked perfectly for a few minutes and without changing any code it just stopped working.
Where am I going wrong?

You need to pass root as an argument to com1
Also, you only need to start mainloop once, and that should probably be in the main file. You do not need to call it each time you create a new window.

Thanks everyone that answered,
Decided to bypass the problem with better structuring in a single file. :)

Related

Tkinter overrideredirect not working in Mac OS X

I'm using the latest version of Mac OS, and Python 3.9. I tried using the overrideredirect to delete the title bar and add my own. However, the result does not show the window. The app is seen in the dock, and the menu bar. But it is not displayed.
My code:
from tkinter import *
root = Tk()
def move_window(event):
root.geometry('+{0}+{1}'.format(event.x_root, event.y_root))
root.overrideredirect(True)
root.geometry('400x100+200+200')
title_bar = Frame(root, bg='white', relief='raised', bd=2)
close_button = Button(title_bar, text='X', command=root.destroy)
window = Canvas(root, bg='black')
title_bar.pack(expand=1, fill=X)
close_button.pack(side=RIGHT)
window.pack(expand=1, fill=BOTH)
title_bar.bind('<B1-Motion>', move_window)
root.mainloop()
The same code works well in windows.
Thanks in advance! :)
On Macs, we need two calls of overrideredirect to remove the border.
Do it like this:
root.overrideredirect(False)
root.overrideredirect(True)
But note that certain events might fail to bind properly, per this post

tkinter window works well only in the first execution

I've been trying to build a tkinter window that has some Check buttons, an image, and a button. I use the Spyder IDE and the code works just fine when I open Spyder and run it for the first time. But when I try to execute again, the image doesn't appear, and also apparently the window does not get destroyed by the button I've created. Is there something wrong with my code?
Here is my code:
import tkinter as tk # GUI configuration
from PIL import ImageTk, Image
# Window to select the analysis actions
config_window = tk.Tk()
config = { # Dictionary with variables that control what the algorithm will do
"EDIT_FILES": tk.BooleanVar(),
"RMS_ANALYSE": tk.BooleanVar(),
"WATERFALL_FFT": tk.BooleanVar()
}
config_window.title('Analysis settings')
label = tk.Label(config_window, text='Please check the boxes corresponding to the operations you would like to do',\
background='red')
label.grid(row=0, sticky='n')
tk.Checkbutton(config_window, text='Edit the files created from the sensor measurements', \
variable=config["EDIT_FILES"]).grid(row=1, sticky='w')
tk.Checkbutton(config_window, text='RMS analysis', \
variable=config["RMS_ANALYSE"]).grid(row=2, sticky='w')
tk.Checkbutton(config_window, text='FFT analysis', \
variable=config["WATERFALL_FFT"]).grid(row=3, sticky='w')
image = Image.open("logo.png").resize((220,80), Image.ANTIALIAS)
logo = ImageTk.PhotoImage(image, size=10)
im_label = tk.Label(image=logo)
im_label.image = logo
im_label.grid(row=4, sticky='w')
tk.Button(config_window, text='Ok', width=10, command=config_window.destroy).grid(row=4, sticky='e')
config_window.mainloop()

tkinter: Frame in Toplevel displayed in parent

I have currently two problems with Toplevel instances in Tkinter.
First and most important: I want to display a popup window and place 2 frames in it for better arangement in grid, but it doesn't work as I expect it to work:
import tkinter
root = tkinter.Tk()
tkinter.Button(root, text="ABC").grid(column=0, row=0)
tkinter.Label(root, text="FOO").grid(column=1, row=1)
win = tkinter.Toplevel()
f1 = tkinter.Frame(win).grid(row=0, column=0)
f2 = tkinter.Frame(win).grid(row=1, column=1)
tkinter.Label(f1, text="FRAME 1").grid()
tkinter.Label(f2, text="FRAME 2").grid()
root.mainloop()
I would expect "FRAME 1" and "FRAME 2" to be placed in the Toplevel window, but they are actually placed in root. How do I fix this?
Second, less important: The popup window in the code above is spawning behind the root window, while I would like it to be placed in front of root, how do I achieve this?
You set your frames f1 and f2 to the return-value of the grid() command, which is None, therefore tkinter.Label(f1, text="FRAME 1").grid() does not work as you expect.
Try something like this:
win = tkinter.Toplevel()
f1 = tkinter.Frame(win)
f1.grid(row=0, column=0)
tkinter.Label(f1, text="FRAME 1").grid()
When setting your geometry manager be it grid(), pack() or place() and you need to be able to interact with that widget later you will need to assign the widget to a variable and then apply the geometry manager on a new line using that variable name. This way your variable will not be a value of None but rather the proper widget. This happens because the geometry managers all return None.
Next the reason your labels are on the wrong windows is because when your labels try to connect with f1 and f2 they are not able to find a proper tkinter container due to the values being None so it defaults to the root tkinter window in an attempt to be place on something.
With fixing the None issues you will also fix your label issue.
To address the matter of your top level window not being in front of your root window there are a couple of things you can do. The main reason this is happening is how your code is generating the top level at __init__ rather than later with a button or a timed event.
If you really need your top level window to open at the same time as root you can use after() and a function to do this and it will be placed on top. If you do not need it right when the window opens you may want to assign a command to a button to run a function that builds the top window.
Here is an example with after():
import tkinter as tk
root = tk.Tk()
def create_top():
win = tk.Toplevel(root)
f1 = tk.Frame(win)
f1.grid(row=0, column=0)
f2 = tk.Frame(win)
f2.grid(row=1, column=1)
tk.Label(f1, text="FRAME 1").grid()
tk.Label(f2, text="FRAME 2").grid()
tk.Button(root, text="ABC").grid(column=0, row=0)
tk.Label(root, text="FOO").grid(column=1, row=1)
root.after(10, create_top)
root.mainloop()
Here is an example with a button:
import tkinter as tk
root = tk.Tk()
def create_top():
win = tk.Toplevel(root)
f1 = tk.Frame(win)
f1.grid(row=0, column=0)
f2 = tk.Frame(win)
f2.grid(row=1, column=1)
tk.Label(f1, text="FRAME 1").grid()
tk.Label(f2, text="FRAME 2").grid()
tk.Button(root, text="ABC", command=create_top).grid(column=0, row=0)
tk.Label(root, text="FOO").grid(column=1, row=1)
root.mainloop()

Destroy window not closing all windows properly

I have two queries in this section.
In my code i have created two frames under root, the first frame have "NEXT" button to go on second frame. In second frame there is Run button, which has mapped with close_window function. It should close all windows properly. But in my case not closing it.
When i click "Run" i need to close all windows and need to execute another script on the same directory. Is that possible to do it ?
from Tkinter import *
def close_window():
frame2.destroy()
frame1.destroy()
def swap_frame(frame):
frame.tkraise()
root = Tk()
root.geometry("900x650+220+20")
root.title("Testing")
root.configure(borderwidth="1", relief="sunken", cursor="arrow", background="#dbd8d7", highlightcolor="black")
root.resizable(width=False, height=False)
frame2 = Frame(root, width=900, height=650)
frame1 = Frame(root, width=900, height=650)
Button1 = Button(frame1, text="Next", width=10, height=2, bg="#dbd8d7", command=lambda: swap_frame(frame2))
Button1.place(x=580, y=580)
Button2 = Button(frame2, text="Run", width=10, height=2, bg="#dbd8d7", command=close_window,)
Button2.place(x=580, y=580)
frame2.grid(row=0, column=0)
frame1.grid(row=0, column=0)
root.mainloop()
what is wrong in the code?
"Destroy window not closing all windows properly"
Nor should it. destroy method destroys a widget, and when a widget is destroyed so are its children.
Since neither frame1 nor frame2 are 'windows' or a window's parents, there's no window destruction taking place.
"When I click "Run" I need to close all windows and need to execute another script in the same directory. Is that possible to do it?"
It is possible. Use quit on any GUI object, instead of destroy. It stops the mainloop, hence destroying the entire GUI. In that it solves the first problem as well. Then import another_script:
...
def close_window():
frame1.quit()
...
root.mainloop()
import another_script

python tkinter clicking on button to open new window

I've made 3 buttons on my window. I choosed that the main window should have a specific background image and a full screen.
Now there is a problem. I would like to move to a new window (page) (with an other background and other things) by clicking on button 3.
Things i tryd:
from Main.Info.travelhistry import *
I've added this to the main window to open a new python file with the code of the second screen that has to open when clicking on button 3. But I found out that if I do this both windows will open when running main window.
I added root1 = Tk() at the beginning, root1.mainloop() at the end and between them the code for the other window. But this won't work also, its opening 2 windows like above.
Those were all my attempts and i cant figure out a better way. I can but the background would stay the same. But I have to change the background for the new window to a background image i made...
Any idea what im doing wrong?
from tkinter import *
from tkinter.messagebox import showinfo
from Main.Info.travelhistry import *
def clicked1():
bericht = 'Deze functie is uitgeschakeld.'
showinfo(title='popup', message=bericht)
root = Tk()
a = root.wm_attributes('-fullscreen', 1)
#Hoofdmenu achtergrond
C = Canvas(root, bg="blue", height=250, width=300)
filename = PhotoImage(file = "test1.png")
background_label = Label(root, image=filename)
background_label.place(x=0, y=0, relwidth=1, relheight=1)
C.pack()
# Geen OV-chipkaart button
b=Button(master=root, command=clicked1)
photo=PhotoImage(file="button1.png")
b.config(image=photo,width="136",height="53", background='black')
b.place(x=310, y=340)
#Buitenland button
b2=Button(master=root, command=clicked1)
photo1=PhotoImage(file="button2.png")
b2.config(image=photo1,width="136",height="53", background='black')
b2.place(x=490, y=340)
#Reis informatie
b3=Button(master=root)
photo2=PhotoImage(file="button3.png")
b3.config(image=photo2,width="136",height="53", background='black')
b3.place(x=680, y=340)
root.mainloop()
root2.mainloop()
You shouldn't call more than one Tk() window.
Instead, tkinter has another widget called Toplevel which can be used to generate a new window.
See below for an example:
from tkinter import *
root = Tk()
def command():
Toplevel(root)
button = Button(root, text="New Window", command=command)
button.pack()
root.mainloop()
This one opens new window that you can edit.
from tkinter import *
Window = Tk()
def Open():
New_Window = Tk()
#You can edit here.
New_Window.mainloop()
Btn1 = Button(text="Open", command=Open)
Bt1n.pack()
Window.mainloop()

Categories