How do I open a new window using a link in tkinter .
(For eg : in a login window i want to add a link that says "New user ? click here" and when I click on "click here" it takes me to the register window .
Please help me
enter image description here
[1]: https://i.stack.imgur.com/K5GV0.png
Please click the above link to see the image
Creating new toplevel windows works almost exactly the same as creating new widgets.
Toplevel windows are created using the Toplevel function:
t = Toplevel(parent)
Unlike regular widgets, you don't have to "Grid" a toplevel fo it to appear on screen. Once you've created a toplevel you can add children widgets within and grid them like in the main window. In other words toplevel behaves exactly like the automatic created root window.
To destroy a window use the method:
window.destroy()
You can open new windows in tkinter with the tkinter.Toplevel() command.
import tkinter as tk
class Gui:
"""Gui class"""
def __init__(self):
self.root = tk.Tk()
self.new_window = tk.Button(master=self.root, text="Open new window", width=20, pady=4, command=self.new_window)
self.new_window.pack()
self.root.mainloop()
def new_window(self):
"""Create a new top level window"""
new_window = tk.Toplevel()
tk.Label(master=new_window, text="This is a new window").pack()
if __name__ == '__main__':
Gui()
You can create a function to open a new window and then bind it to that Label, for example:
import tkinter as tk
def newWindow():
# Window object (top level)
newWindow = Toplevel(master)
# Title
newWindow.title("New Window 1")
# Geometry
newWindow.geometry("300x300")
root = tk.Tk()
label = tk.Label(text="Hello!", width=50, height=10, master=root)
label.pack()
label.bind("<Button-1>", newWindow)
Related
I wonder if someone could tell me if its possible to update toplevel windows using external functions. I've replicated my issue below what I need to do is update the Toplevel(master) using the function updatelabel(). I have used similar external function to update items in root which works like a dream. However, with the top level window I always get the
NameError: name 'newWindow' is not defined
The only work around I found was to kill the newWindow using newWindow.destroy() on each load but this method makes the screen pop up and then close again which doesn't look pretty. Any help most welcome thanks.
from tkinter import *
from tkinter.ttk import *
master = Tk()
master.geometry("200x200")
def updatelabel():
Label(newWindow,
text="I changed").pack()
def openNewWindow():
# Toplevel object which will
# be treated as a new window
newWindow = Toplevel(master)
# sets the title of the
# Toplevel widget
newWindow.title("New Window")
# sets the geometry of toplevel
newWindow.geometry("200x200")
# A Label widget to show in toplevel
Label(newWindow,
text="I want to change").pack()
button1 = Button(newWindow,
text="Click me to change label", command=updatelabel).pack()
btn = Button(master,
text="open a new window",
command=openNewWindow)
btn.pack(pady=10)
mainloop()
Your “newWindow” is defined in your “openNewWindow” function and so it basically only exists in there, you could probably fix this by either defining “newWindow” outside of the function, or by using it as an argument(just add it to the brackets and give it a name in the function itself’s brackets) calling “updateLabel”
I think this should work, though I haven’t worked with tkinter in a bit so don’t blame me if it doesn’t
from tkinter import *
from tkinter.ttk import *
master = Tk()
master.geometry("200x200")
def updatelabel(newWindow):
Label(newWindow,
text="I changed").pack()
def openNewWindow():
# Toplevel object which will
# be treated as a new window
newWindow = Toplevel(master)
# sets the title of the
# Toplevel widget
newWindow.title("New Window")
# sets the geometry of toplevel
newWindow.geometry("200x200")
# A Label widget to show in toplevel
Label(newWindow,
text="I want to change").pack()
button1 = Button(newWindow,
text="Click me to change label", command= lambda: updatelabel(newWindow)).pack()
btn = Button(master,
text="open a new window",
command=openNewWindow)
btn.pack(pady=10)
mainloop()
So I made this simple code to recreate the way I want my actual app to behave (sorry, if I didn't use oop and really new into this):
import tkinter as tk
from tkinter import ttk
def OpenSecondToplevel():
Top2=tk.Toplevel(root)
Top2.geometry("250x200")
Top2.grab_set()
Top2.title("TopLevel 2")
Label = tk.Label(Top2, text="This is Toplevel 2")
Label.pack()
def OpenFirstToplevel():
Top1=tk.Toplevel(root)
Top1.geometry("250x200")
Top1.grab_set()
Top1.title("TopLevel 1")
Button2 = tk.Button(Top1, text="Open Toplevel 2", command=OpenSecondToplevel)
Button2.pack()
root = tk.Tk()
root.title("Main")
root.geometry("250x200")
Frame1 = tk.Frame(root)
Button1 = tk.Button(Frame1, text="Open Toplevel 1", command=OpenFirstToplevel)
Frame1.pack()
Button1.pack()
root.mainloop()
I recorded a video, explaining my issue, because I been looking a lot about Toplevels behavior and I cant seem to find a way to fix it. I hope the video is understandable sorry about the bad English is not my main language, if you have any question you can ask me, thank you!
https://www.youtube.com/watch?v=Ks2zRU0fOJM
For your case, the simple way is to save the current window which has grab_set() in OpenSecondToplevel(), wait for second toplevel to close and then resume the grab_set() state of saved window:
def OpenSecondToplevel():
win = root.grab_current() # save the current window which has grab_set()
# win is None is no window has grab_set()
Top2=tk.Toplevel(root)
Top2.geometry("250x200")
Top2.grab_set()
Top2.title("TopLevel 2")
Label = tk.Label(Top2, text="This is Toplevel 2")
Label.pack()
if win:
# wait until current toplevel is destroyed
win.wait_window(Top2)
# resume grab_set() for saved window
win.grab_set()
How do you make a button open a duplicate window of the main page in a new window?
What would the python code be to do this with Tkinter?
For clarification, in notepad++ when you right click on the tab that you are in, it shows you a whole menu.
Then, there is a dropdown menu with an option that says, open in a new instance or move to a new instance.
This would then open the tab you selected into a new tab/window.
I haven't tried anything yet but I did look up about how to do this type of thing and there were no results on what exactly I wanted to do.
Can you try to show me an example of how what I need to do can be done?
Code:
Found Here
The simplest solution is to make your window be a subclass of Toplevel. Then, each time you need a new window, create a new instance of the class.
You can then leave the root window blank and hide it so that you only see your custom windows. It's important to make sure that you destroy the root window after the user has deleted the last application window, or else you'll end up with an invisible window that will be hard to kill.
Here is a bit of a contrived example:
import tkinter as tk
class AppWindow(tk.Toplevel):
def __init__(self, root):
tk.Toplevel.__init__(self, root)
self.root = root
menubar = tk.Menu(self)
windowMenu = tk.Menu(menubar)
windowMenu.add_command(label="New Window", command=self.new_window)
windowMenu.add_command(label="Quit", command=root.destroy)
menubar.add_cascade(label="Window", menu=windowMenu)
self.configure(menu=menubar)
self.text = tk.Text(self)
self.vsb = tk.Scrollbar(self, orient="vertical", command=self.text.yview)
self.text.configure(yscrollcommand=self.vsb.set)
self.vsb.pack(side="right", fill="y")
self.text.pack(side="left", fill="both", expand=True)
# call a function to destroy the root window when the last
# instance of AppWindow is destroyed
self.wm_protocol("WM_DELETE_WINDOW", self.exit_on_last_window)
def new_window(self):
AppWindow(self.root)
def exit_on_last_window(self):
"""Destroy the root window when no other windows exist"""
self.destroy()
if not any([window.winfo_exists() for window in self.root.winfo_children()]):
self.root.destroy()
def quit(self):
self.root.destroy()
# create the root, then hide it. The app will create its
# own windows as Toplevels
root = tk.Tk()
root.withdraw()
# create the first window, then start the event loop
AppWindow(root)
tk.mainloop()
Preface:
I have a Python ControlGPIO code with a working GUI (let us call it MainGUI).
I wish to have a dialog pop up window, prior to running MainGUI, in a way that the user can enable/ disable features in MainGUI. BUT MainGUI should start running only after dialog pop up window is closed.
My question is: How can I make a popup window that will postpone MainGUI untill it is closed?
Code below- boot_windows is my dialog pop up window (where all the enable/disable checkboxes will be ), BUT obviously does not postpone App as I need
root = Tk()
#output_gpioPins = [4,22,6,26]
#input_gpioPins = [3,21,5,27]
#ip = '192.168.2.112'
boot_windows = Toplevel(root)
text1 = ttk.Label(boot_windows, text="Hello World !!!")
text1.grid()
App = ContorlGPIOWindow(root, ip = '192.168.2.113', with_sf_bt=1, with_hw_bt=1, switch_names=['Light Kitchen','Light Room1', 'Window1', 'Window2'])
root.mainloop()
You can't do precisely what you want. Widgets exist in a tree-like structure. All windows except the root require a root window. The root window must be created first (which is why it's called the root window).
If you don't want the user to see it, you can hide it until it is ready to be displayed.
import tkinter as tk
root = tk.Tk()
root.withdraw()
boot_window = tk.Toplevel(...)
...
You can then call root.deiconify() when you are ready for it to be visible.
Another common solution is to use the root window for your dialog or splash screen or whatever, and then simply replace its contents with the real contents when you're ready.
As for how to wait for the popup... the root window has a method named wait_window which will enter the event loop and not return until the given window has been destroyed.
Here's an example of it's use:
import Tkinter as tk
class MainGUI(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Hello, world!")
label.pack(fill="both", expand=True, padx=20, pady=20)
class Popup(tk.Toplevel):
def __init__(self, root):
tk.Toplevel.__init__(self, root)
label = tk.Label(self, text="Click to continue...")
label.pack(fill="both", expand=True, padx=20, pady=20)
button = tk.Button(self, text="OK", command=self.destroy)
button.pack(side="bottom")
if __name__ == "__main__":
root = tk.Tk()
root.withdraw()
popup = Popup(root)
root.wait_window(popup)
main = MainGUI(root)
main.pack(fill="both", expand=True)
root.deiconify()
root.mainloop()
I am starting by making a simple prompt window where the user will fill out the name of the directory to grab images from and where to save a resultant .csv file (and some other info).
After pressing enter in this (in this case) I want this prompt window to close and the main window where all the work will be performed by the user to appear.
In short, is this the correct way to begin structuring the classes for my GUI? Also why does the line:
frame = Frame(master, height=500,padx=20, pady=20)
Not change the formatting/layout of this initial window?
I feel that once i have a solid grasp on how to build this initial window, I will have the proper foundation to continue the rest on my own.
#imports
from Tkinter import *
import glob
from PIL import Image, ImageTk
#end imports
class prompt_window:
def __init__(self, master):
frame = Frame(master, height=500,padx=20, pady=20)
#Build prompt window labels
self.source_label = Label(root, text="Source Directory")
self.destination_label = Label(root, text="Destination Directory")
self.region_sz_label = Label(root, text="Region Size")
self.save_file_name_label = Label(root, text="Save File Name")
#Build prompt window entry forms
self.source_entry = Entry(root)
self.destination_entry = Entry(root)
self.region_sz_entry = Entry(root)
self.save_file_name_entry = Entry(root)
#Build enter button
self.enter_button = Button(root, text="Enter")
#Align labels in prompt window grid
self.source_label.grid(row=0)
self.destination_label.grid(row=1)
self.region_sz_label.grid(row=2)
self.save_file_name_label.grid(row=3)
#Align entry forms in prompt window grid
self.source_entry.grid(row=0, column=1)
self.destination_entry.grid(row=1, column=1)
self.region_sz_entry.grid(row=2, column=1)
self.save_file_name_entry.grid(row=3, column=1)
#Add button
self.enter_button.grid(row=4,column=2)
#create root
root = Tk()
#create prompt window
prompt = prompt_window(root)
#run indefinitely
root.mainloop()
You need to call one of the layout methods (.pack, .grid, or .place) on your Frame to make it visible. In my version of your program I've changed the class name from prompt_window to PromptWindow to conform to the PEP-8 style guide. I've also changed the Tkinter import statement so we aren't cluttering our namespace with all those Tkinter names.
Organizing GUI code is a little different to organizing a plain CLI program. Once we've defined everything we sit in a loop waiting for events to respond to. So for this program we need to set things up so that when the prompt window closes the main window opens and it has access to the data gathered by the prompt window.
You said that you want the prompt window to be a different window to the main window, so we need to create a window for it. A Tkinter program can only have one root window, so we create a Toplevel window to hold the prompt Frame.
You don't need to save the Labels as attributes of the PromptWindow instance since you aren't doing anything with them after you create them.
I've changed the Entry widgets slightly: I've given each of them a StringVar to hold their data. This makes it possible to access that data after the prompt window is closed. When a widget's parent window is closed you can't access it anymore. So instead of saving each Entry as an attribute of PromptWindow we instead save the associated StringVar.
When the "Enter" button is pressed or the prompt window's close widget is pressed we close the prompt window and make the main window visible.
I've created a simple MainWindow class that contains a button that lets us print the data gathered by the prompt window.
import Tkinter as tk
class PromptWindow(object):
def __init__(self, master):
self.master = master
self.win = tk.Toplevel(master)
self.win.title("Prompt Window")
# Intercept close window events so that when the user closes this window
# (via the close widget or the Enter button) the main window reopens
self.win.protocol("WM_DELETE_WINDOW", self.close)
frame = tk.Frame(self.win, height=500,padx=20, pady=20)
frame.pack()
# Build prompt window labels
tk.Label(frame, text="Source Directory").grid(row=0)
tk.Label(frame, text="Destination Directory").grid(row=1)
tk.Label(frame, text="Region Size").grid(row=2)
tk.Label(frame, text="Save File Name").grid(row=3)
# Build prompt window entry widgets
self.source = tk.StringVar()
tk.Entry(frame, textvariable=self.source).grid(row=0, column=1)
self.destination = tk.StringVar()
tk.Entry(frame, textvariable=self.destination).grid(row=1, column=1)
self.region_sz = tk.StringVar()
tk.Entry(frame, textvariable=self.region_sz).grid(row=2, column=1)
self.save_file_name = tk.StringVar()
tk.Entry(frame, textvariable=self.save_file_name).grid(row=3, column=1)
# Build enter button
tk.Button(frame, text="Enter", command=self.close).grid(row=4,column=2)
def close(self):
# Close this window
self.win.destroy()
# Reopen the main window
self.master.deiconify()
class MainWindow(object):
def __init__(self):
# Create root window
root = tk.Tk()
# and make it invisible
root.withdraw()
root.title("Main Window")
# Add some widgets
tk.Label(root, text="This is the main window").pack()
tk.Button(root, text="Show data", command=self.show_data).pack()
# Create prompt window
self.prompt = PromptWindow(root)
# Loop forever
root.mainloop()
# Display the data gathered by the prompt window
def show_data(self):
prompt = self.prompt
src = prompt.source.get()
dest = prompt.destination.get()
region = prompt.region_sz.get()
fname = prompt.save_file_name.get()
fmt = 'src: {!r}, dest: {!r}, region: {!r}, fname: {!r}'
print(fmt.format(src, dest, region, fname))
MainWindow()