Placing Tkinter Frame in another Frame - python

I am trying to experiment and get the button to only display the label when the button is clicked instead it is opening up another GUI window. The main frame is called secret message. Within this when i click onto the button it should then replace the empty place with the label in row=2.
Could someone explain to me how i can raise the label rather than just opening up a new window. All code is functional but i want another way around this, i am new to python.
from tkinter import *
def topLevel():
top=Toplevel()
top.geometry("300x200")
root=Tk()
root.title("Secret Message")
button1 = Button(text="Push this button to see hidden message!", width =60, command=topLevel)
button1.grid(row=1, column=0)
label1 = Label(width=50, height=10, background="WHITE", text= "There is no secret!")
label1.grid(row=2, column=0)
root.mainloop()

You question title has nothing to do with your question.
To update the geometry of your label you simple need to tell the function where you want the label on the container you set up your label in. In this case you do not define the container so the widgets default to the root window.
Here is a working example that will update the label geometry when you press the button.
from tkinter import *
root=Tk()
root.title("Secret Message")
def grid_label():
label1.config(text="There is no secret!")
Button(root, text="Push this button to see hidden message!", width=60, command=grid_label).grid(row=1, column=0)
label1 = Label(root, width=50, height=10, background="WHITE")
label1.grid(row=2, column=0)
root.mainloop()

Related

Tkinter toplevel window is not defined

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()

I am trying to have my "multible label widget" as well as my "creating buttons" but when when i get one to work the other does not

Here is the code that i have scripted i know it looks bad i am a total noob at this but i really need help. I want my GUI to show the "welcome" and "this gui was written by..." message at the bottom and then add the button functions that i am later going to intergrate with a api.
from cProfile import label
from tkinter import *
root = Tk()
def create_label():
# creating multible label widgets
myLabel1= Label(root,text="Welcome")
myLabel2= Label(root,text=" ")
myLabel3= Label(root,text=" ")
myLabel4= Label(root,text=" ")
myLabel5= Label(root,text="This Gui was written by Seha")
# Showing it on the screen and putting it in rows and columns
myLabel1.grid(row=0, column=10)
myLabel2.grid(row=1, column=10)
myLabel4.grid(row=2, column=10)
myLabel3.grid(row=3, column=10)
myLabel5.grid(row=4, column=10)
create_label.pack()
def create_button():
# Creating buttons
myButton= Button(root, text="Click on this button to check floor price for a specific collection: ",command=label)
myButton2= Button(root, text="Click on this button to check the 24h volume for a specific collection:", command=label)
myButton.pack()
myButton2.pack()
root.mainloop()
This is what my code looks like and i screenshotted what the gui shows
[1]: https://i.stack.imgur.com/jJnxu.png

subroot window editing - tkinter

I'm sure this is going to amount to my misunderstanding of what I'm calling. So I'm trying to make edits to a second window but I don't know that I'm doing it right as it doesn't appear to change. Under def open_win() I created a second window registration(which is supposed to be the equivalent of root). I got the second window to take the Screen position/size but for some reason it wont add the label/entry
from tkinter import *
from functools import partial
#outputs to IDLE
def validateLogin(username, password):
print("username entered :", username.get())
print("password entered :", password.get())
return
#centering Registration page
def open_win():
registration=Toplevel(root)
registration.title("Registration Page")
window_width=600
window_height=400
screen_width =registration.winfo_screenwidth()
screen_height =registration.winfo_screenheight()
center_x=int(screen_width/2-window_width/2)
center_y=int(screen_height/2-window_height/2)
registration.geometry(f'{window_width}x{window_height}+{center_x}+{center_y}')
#registration label and text entry box
usernameLabel=Label(registration, text="User Name").grid(row=0, column=1)
username=StringVar()
usernameEntry=Entry(registration, textvariable =UserName).grid(row=0, column=2)
#Root Window
root=Tk()
root.title('Sign in Page')
#centering window
window_width=600
window_height=400
screen_width =root.winfo_screenwidth()
screen_height =root.winfo_screenheight()
center_x=int(screen_width/2-window_width/2)
center_y=int(screen_height/2-window_height/2)
root.geometry(f'{window_width}x{window_height}+{center_x}+{center_y}')
#username label and text entry box
usernameLabel=Label(root, text="User Name").grid(row=0, column=1)
username=StringVar()
usernameEntry=Entry(root, textvariable=username).grid(row=0, column=2)
#password label and password entry box
passwordLabel=Label(root,text="Password").grid(row=1, column=1)
password=StringVar()
passwordEntry=Entry(root, textvariable=password, show='*').grid(row=1, column=2)
validateLogin=partial(validateLogin, username, password)
#login button
loginButton=Button(root, text="Login", command=validateLogin).grid(row=4, column=1)
SignUpButton=Button(root, text="Sign up", command=open_win).grid(row=4, column=2)
#registration label and text entry box
usernameLabel=Label(registration, text="User Name").grid(row=0, column=1)
username=StringVar()
usernameEntry=Entry(registration, textvariable =UserName).grid(row=0, column=2)
root.mainloop()
Your main issue with not being able to work with the 2nd window is basically a issue of namespace. Your registration variable is stored in the local namespace of the function. If you want to edit it from outside the function like you attempt to do then you need your variable to be in the global namespace.
Because you appear to try and write the same label and entry field a couple of times to the registration top window then I suspect you do not actually need to edit it from outside the function but need to edit it when you created the window.
I have cleaned up your code a little and condensed it to make it a little easier to read.
You should first import tkinter ask tk instead of importing *. This will help prevent any issue with overwriting imports down the road and it makes it a little easier to ID what is referencing a tk widget or some other function.
You use 2 different naming conventions in your code. Chose one and stick with that. It will improve readability. I recommend following PEP8 guidelines.
Items that are not going to be changed later do not need to have variables assigned to them so you can clean up your code a bit there also.
You do not need to go the extra mile to use StringVar here. We can simply pull directly from the entry field as long as the geometry manager (ie grid()) is assigned on a new line so you can still access the variable reference for the entry field.
I am not sure what you were needing partial() for and I think you should use lambda instead in this situation.
If you have any questions let me know.
import tkinter as tk
def validate_login(username, password):
print("username entered :", username.get())
print("password entered :", password.get())
def open_win():
reg = tk.Toplevel(root)
reg.title("Registration Page")
reg.geometry(f'600x400+{int(reg.winfo_screenwidth()/2-600/2)}+{int(reg.winfo_screenheight()/2-400/2)}')
tk.Label(reg, text="User Name").grid(row=0, column=1)
r_un = tk.Entry(reg)
r_un.grid(row=0, column=2)
root = tk.Tk()
root.title('Sign in Page')
root.geometry(f'600x400+{int(root.winfo_screenwidth()/2-600/2)}+{int(root.winfo_screenheight()/2-400/2)}')
tk.Label(root, text="User Name").grid(row=0, column=1)
un = tk.Entry(root)
un.grid(row=0, column=2)
tk.Label(root, text="Password").grid(row=1, column=1)
pw = tk.Entry(root, show='*')
pw.grid(row=1, column=2)
tk.Button(root, text="Login", command=lambda u=un, p=pw: validate_login(u, p)).grid(row=4, column=1)
tk.Button(root, text="Sign up", command=open_win).grid(row=4, column=2)
root.mainloop()

How to make tkinter right click menu work on one widget only?

Is there a simple way to get the right click menu to open on texty only and not the whole window?
This was a quick mashup to illustrate my question. Inheriting from texty on line 25 was a shot in the dark, which didnt work, but it's close to a simple solution, like I am seeking. I was hoping to avoid programming a whole class each time I want to set a right click menu.
from tkinter import *
from tkinter import ttk
def menu_popup(event):
try:
popup.tk_popup(event.x_root, event.y_root, 0)
finally:
popup.grab_release()
win = Tk()
win.geometry("600x550+125+125")
e = Entry(win, width=50, font=('Helvetica', 11))
e.pack()
e.insert(0, "Some text....")
label = Label(win, text="Right-click to see a menu", font= ('Helvetica 18'))
label.pack(pady= 40)
texty=Text(win, height=10)
texty.pack()
popup = Menu(texty, tearoff=0)
popup.add_command(label="New")
popup.add_separator()
popup.add_command(label="Open")
popup.add_separator()
popup.add_command(label="Close")
win.bind("<Button-3>", menu_popup)
button = ttk.Button(win, text="Quit", command=win.destroy)
button.pack()
mainloop()
The widget on which the callback should be executed for the respective event is determined by the widget you call bind on(and the level of bind too*). So if you want the event to be identified within texty, then apply binding to it.
texty.bind("<Button-3>", menu_popup)
* There is bind_all which executes no matter which widget has focus or is called upon. Read 54.1. Levels of binding for more info.

Toplevel from a Toplevel behavior on Tkinter Python

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()

Categories

Resources