I'm currently writing a library system and, in order to better understand how to change between frames, have so far have written code for a screen the user is met with when they first use the program as shown below:
import tkinter as tk
import json
window = tk.Tk() # creates a window
width = 474 # sets the width and height of the screen
height = 266
screen_width = window.winfo_screenwidth() # finds the width of the user's screen
screen_height = window.winfo_screenheight()
center_x = int(screen_width / 2 - width / 2)
center_y = int(screen_height / 2 - height / 2)
window.geometry(f'{width}x{height}+{center_x}+{center_y}') # sets the width, height, and positioning of the window
window.title("Library System") # sets title of window
window.resizable(False, False) # Prevents the window being resized by both the x and y coordinates
welcome = tk.Frame(width=200, height=200, background="light cyan")
ChangeInfo = tk.Frame(window, width=400, height=200)
ChangeInfo.pack(fill='both', expand=True, padx=0, pady=0)
def WelcomeScreen():
greeting = tk.Label(welcome, text="Welcome", font=("comic sans", 15), bg ='light cyan') # creates a lable with text
greeting.pack()
explaination = tk.Label(welcome, text="This is your first time using this program so please click the button below to "
"enter in \n the username "
"and password you will be using to log into the system in the future"
"", font=("comic_sans", 9), bg="light cyan")
explaination.place(x = (width)/2, y= 50, anchor='center')
login_button = tk.Button(welcome, text="Set username and password", height=3, width=22,
font=("comic_sans", 10), bg = "turquoise")
login_button.place(x= width / 2, y= height / 2, anchor='center')
window.mainloop()
WelcomeScreen()
The only thing that is displayed at the moment is the window and its title. How do I display the frame instead of only the window?
If you want to show the welcome frame initially, you need to call welcome.pack(...) instead of ChangeInfo.pack(...).
Related
I have successfully made a 'next' and 'back' button for the firstDicePage and secondDicePage functions so that I could return to either of the pages when needed. However, I am trying to avoid making multiple pages pop up every time I hit those buttons. I heard of .withdraw(), but I am unsure how to apply it in this code.
from tkinter import *
from tkinter import simpledialog
from tkinter import ttk
from tkinter import filedialog
from tkinter.font import Font
import tkinter as tk
import from PIL import Image, ImageTk
import tkinter
import sys
import random
def firstDicePage():
firstWindow = tkinter.Toplevel(window) # Create new window.
firstWindow.title("Dice Roller Generator")
# Change Icon photo
image = PhotoImage(file = "C:\\Users\\alexi\\Desktop\\Project Photos\\Dice logo.png")
firstWindow.iconphoto(False, image)
# Center
app_width = 900
app_height = 600
screen_width = firstWindow.winfo_screenwidth()
screen_height = firstWindow.winfo_screenheight()
x = (screen_width / 2) - (app_width / 2)
y= (screen_height / 2) - (app_height / 2)
firstWindow.geometry(f'{app_width}x{app_height}+{int(x)}+{int(y)}')
Label(firstWindow, text = "\n\nSelect How Many Dice You Want to Roll!", font='Helvetica 16 bold').pack()
img = ImageTk.PhotoImage(Image.open("Dice.png"))
my_label = Label(firstWindow, image=img)
my_label.img = img # Save reference to image.
my_label.pack()
counter = tkinter.IntVar()
def increase():
counter.set(min(10, counter.get() + 1))
def decrease():
counter.set(max(0, counter.get() - 1))
lbl = Label(firstWindow, textvariable = counter, font='Helvetica 16 bold')
lbl.place(x=450, y=330)
btn1 = Button(firstWindow, text="+", font='Helvetica 16 bold', padx = 8, pady = 5, command = increase, fg="dark green", bg = "white")
btn1.place(x=499, y=320)
btn2 = Button(firstWindow, text ="-", font='Helvetica 16 bold', padx = 11.1, pady = 5, command = decrease, fg="dark green", bg = "white")
btn2.place(x=375, y=320)
btn3 = Button(firstWindow, text = "Next", font='Helvetica 16 bold', command=lambda: secondDicePage())
btn3.place(x = 800 , y = 530)
def secondDicePage():
secondWindow = tkinter.Toplevel(window) # Create new window.
secondWindow.title("Dice Roller Generator")
# Change Icon photo
image = PhotoImage(file = "C:\\Users\\alexi\\Desktop\\Project Photos\\Dice logo.png")
secondWindow.iconphoto(False, image)
# Center
app_width = 900
app_height = 600
screen_width = secondWindow.winfo_screenwidth()
screen_height = secondWindow.winfo_screenheight()
x = (screen_width / 2) - (app_width / 2)
y= (screen_height / 2) - (app_height / 2)
secondWindow.geometry(f'{app_width}x{app_height}+{int(x)}+{int(y)}')
btn3 = Button(secondWindow, text = "Back", font='Helvetica 16 bold', command=lambda: firstDicePage())
btn3.place(x = 30 , y = 530)
def secondButton():
# Toplevel object which will
# be treated as a new window
secondWindow = Toplevel(window)
secondWindow.title("Dice Roller Generator")
# Change Icon photo
img = PhotoImage(file = "C:\\Users\\alexi\\Desktop\\Project Photos\\Dice logo.png")
secondWindow.iconphoto(False, img)
# Center
app_width = 600
app_height = 400
screen_width = secondWindow.winfo_screenwidth()
screen_height = secondWindow.winfo_screenheight()
x = (screen_width / 2) - (app_width / 2)
y= (screen_height / 2) - (app_height / 2)
secondWindow.geometry(f'{app_width}x{app_height}+{int(x)}+{int(y)}')
# A Label widget to show in top-level
Label(secondWindow, text = "\n\nSelect What/How Many Dice You Want to Roll!", font='Helvetica 16 bold').pack()
# Create the window(root interface)
window = Tk()
# Create a title
window.title("Dice Roller Generator")
# Change Icon photo
img = PhotoImage(file = "C:\\Users\\alexi\\Desktop\\Project Photos\\Dice logo.png")
window.iconphoto(False, img)
# Center
app_width = 600
app_height = 400
screen_width = window.winfo_screenwidth()
screen_height = window.winfo_screenheight()
x = (screen_width / 2) - (app_width / 2)
y= (screen_height / 2) - (app_height / 2)
window.geometry(f'{app_width}x{app_height}+{int(x)}+{int(y)}')
# Create a label widget
lbl = Label(window, text = "\n\n\nChoose the Kind of Die You Want to Roll", font='Helvetica 16 bold')
#Packing(size), Shove it in the screen
lbl.pack()
btn1 = Button(window, text = "Regular Dice", padx = 15, pady = 15, command = firstDicePage)
btn1.place(x=145, y=130)
btn2 = Button(window, text = "D&D Dice", padx = 20, pady = 15, command = secondButton)
btn2.place(x=355, y=130)
btn3 = Button(window, text="Exit", padx = 15, pady = 5, command = window.quit)
btn3.place(x=275, y=335)
window.mainloop()
I'm currently trying to create a command centre to integrate with one of my other python programs, however, I am quite new to Tkinter, and as such, I was wondering if there was a way to "reset" a window that has widgets in it so that I can have a clean window to place new widgets in, without storing any data or using system resources. Here is the code I currently have:
import tkinter
tk = tkinter
window = tk.Tk()
def login():
window.title("SCC: Login")
header = tk.Label(window, text = "Please Login").pack()
frame = tkinter.Label(window, text = "Username").pack()
frame = tkinter.Entry(window).pack()
frame = tkinter.Label(window, text = "Password").pack()
frame = tkinter.Entry(window).pack()
frame = tkinter.Checkbutton(window, text = "Keep Me Logged In").pack()
frame = tkinter.Button(window, text = "Login", command = mainMenu).pack()
window.mainloop()
def mainMenu():
()
window.title("SCC")
tk.Label(window, text = "Welcome to the Sentinel Command Center").pack()
tk.Button(window, text = "Network Utilities", fg = "orange").pack()
tk.Button(window, text = "Image Recognition", fg = "orange").pack()
tk.Button(window, text = "Voice Recognition", fg = "orange").pack()
window.mainloop()
login()
also as a side note i am fully aware the current password form is non functional, its just a placeholder for now until i find a better method of authorization for the code.
Arguably, the easiest way to reset it is to put all of your widgets inside a frame, and then create a function that creates the frame. Then, to do a reset you can destroy the current frame and call your function to recreate it.
Update:
I found a functional if a convoluted method to doing this, just by creating separate windows, then withdrawing the login window once the main menu has been called. Here is the code if you want to use it:
mainWindow = tk.Tk()
loginWindow = tk.Tk()
version = ("v0.1")
def centerwindowLogin(width=300, height=200):
screen_width = loginWindow.winfo_screenwidth()
screen_height = loginWindow.winfo_screenheight()
x = (screen_width/2) - (width/2)
y = (screen_height/2) - (height/2)
loginWindow.geometry('%dx%d+%d+%d' % (width, height, x, y))
def centerwindowMain(width=300, height=200):
screen_width = mainWindow.winfo_screenwidth()
screen_height = mainWindow.winfo_screenheight()
x = (screen_width/2) - (width/2)
y = (screen_height/2) - (height/2)
mainWindow.geometry('%dx%d+%d+%d' % (width, height, x, y))
def login():
loginWindow.title("SCC v0.1")
header = tk.Label(loginWindow, text = "Please Login").pack()
tk.Label(loginWindow, text = "Username").pack()
tk.Entry(loginWindow).pack()
tk.Label(loginWindow, text = "Password").pack()
tk.Entry(loginWindow).pack()
tk.Checkbutton(loginWindow, text = "Keep Me Logged In").pack()
tk.Button(loginWindow, text = "Login", command = mainMenu).pack()
centerwindowLogin(300, 175)
loginWindow.mainloop()
def mainMenu():
loginWindow.withdraw()
mainWindow.title("SCC v0.1")
tk.Label(mainWindow, text = "Welcome to the Sentinel Command Center").pack()
tk.Button(mainWindow, text = "Network Utilities", fg = "orange").pack()
tk.Button(mainWindow, text = "Image Recognition", fg = "orange").pack()
tk.Button(mainWindow, text = "Voice Recognition", fg = "orange").pack()
centerwindowMain(500, 400)
mainWindow.mainloop()
login()
This function can be used to remove all existing widgets:
def wempty(w):
for w in w.winfo_children():
w.destroy()
I'm trying to use Tkinter to create a GUI for a school planner and I want to have users be able to log in and create an account. It might get too lengthy if I try to code the entire project in one file, so I'm trying to split it up. My main file just has:
try:
import tkinter as tk # python 3
from tkinter import font as tkfont # python 3
except ImportError:
import Tkinter as tk # python 2
import tkFont as tkfont # python 2
import TkWindow
app = TkWindow.TkWindow()
app.getRoot().mainloop()
Where my TkWindow file is the file that runs everything. It looks like this:
from tkinter import *
import mainMenu
import CreateAccount
class TkWindow:
def __init__(self):
self.master = Tk() # Makes the window
self.master.wm_title("School Planner")
self.master.config(background="#FFFFFF")
# Master window dimensions
app_width = 1000
app_height = 500
screen_width = self.master.winfo_screenwidth() # Get screen width
screen_height = self.master.winfo_screenheight() # Get screen height
x = int((screen_width / 2) - (app_width / 2)) # X coordinate to center application
y = int((screen_height / 2) - (app_height / 2)) # Y coordinate to center application
self.dimensions = f'{app_width}x{app_height}+{x}+{y}'
self.master.geometry(self.dimensions) # Set master geometry
container = Frame(self.master, width=app_width, height=app_height, relief='raised', borderwidth=5)
# self.currentFrame = Frames.main(self.master)
self.frames = {}
for F in (mainMenu.MainMenu, CreateAccount.CreateAccount):
page_name = F.__name__
frame = F(master=container.master, controller=self)
self.frames[page_name] = frame
self.show_frame("MainMenu")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
def getRoot(self):
return self.master
Where my mainMenu file is:
from tkinter import *
import Fonts
import CreateAccount
class MainMenu(Frame):
def __init__(self, master, controller):
Frame.__init__(self, master)
self.root = master
self.root.title("Benjamin's School Planner")
# TODO: get an icon and find the path of it
# master.iconbitmap('HERE SHOULD GO THE FILE PATH TO THE ICON')
# Master window dimensions
app_width = 1000
app_height = 500
#screen_width = master.winfo_screenwidth() # Get screen width
#screen_height = master.winfo_screenheight() # Get screen height
#x = int((screen_width / 2) - (app_width / 2)) # X coordinate to center application
#y = int((screen_height / 2) - (app_height / 2)) # Y coordinate to center application
#master.geometry(f'{app_width}x{app_height}+{x}+{y}') # Set master geometry
# Set and display welcome message
welcome_label = Label(self.root, text='Welcome to the School Planner', font=Fonts.welcomeFont())
welcome_label.pack()
# Set and display username prompt
username_label = Label(self.root, text='Username', font=Fonts.loginFont())
username_label.place(relx=0.4, rely=0.4, anchor='center')
username_entry = Entry(self.root)
username_entry.place(relx=0.55, rely=0.4, anchor='center')
# Set and display username prompt
password_label = Label(self.root, text='Password', font=Fonts.loginFont())
password_label.place(relx=0.4, rely=0.5, anchor='center')
password_entry = Entry(self.root, show="\u2022")
password_entry.place(relx=0.55, rely=0.5, anchor='center')
# Login button command:
def login():
print("Logged in Successfully")
# Login button creation:
login_button = Button(text='Login',
command=lambda: login(),
bg='Gray', fg='Black', font=Fonts.loginFont())
login_button.place(relx=0.5, rely=0.62, anchor='center')
# 'Show Password' Checkbox creation
checkboxVar = IntVar()
def showPassword():
if checkboxVar.get() == 1:
password_entry.config(show="")
password_entry.update()
elif checkboxVar.get() == 0:
password_entry.config(show="\u2022")
show_password_checkbox = Checkbutton(master,
text="Show Password",
font=Fonts.showPasswordFont(),
variable=checkboxVar,
command=showPassword)
show_password_checkbox.place(relx=0.5, rely=0.7, anchor='center')
# Create Account button creation:
create_account_button = Button(text='Create Account',
command=lambda: controller.show_frame("CreateAccount"),
bg='Gray', fg='Black', font=Fonts.createAccountFont())
create_account_button.place(relx=0.5, rely=0.7, anchor='center')
And my CreateAccount file is:
from tkinter import *
import Fonts
class CreateAccount(Frame):
def __init__(self, master, controller):
Frame.__init__(self, master)
#master.title("Create Account")
master.config(bg='blue')
# Master window dimensions
app_width = 1000
app_height = 500
#screen_width = master.winfo_screenwidth() # Get screen width
#screen_height = master.winfo_screenheight() # Get screen height
#x = int((screen_width / 2) - (app_width / 2)) # X coordinate to center application
#y = int((screen_height / 2) - (app_height / 2)) # Y coordinate to center application
#master.geometry(f'{app_width}x{app_height}+{x}+{y}') # Set master geometry
welcome_label = Label(master, text='We made it to create account', font=Fonts.welcomeFont())
welcome_label.pack()
I'm having trouble where when it runs, it's running both frames at the same time at the beginning and I'm not sure why. Whenever I press the "create account" button, it registers that a frame should switch, but the new one doesn't arise. Does anyone know why?
Hi there i am building a short game in tkinter and would like to be able to output to the user via a label within my tkinter window. I have looked at past questions and found no help apart from getting it to refresh using a button which is not what i want it to do. In short i need to have it refresh everytime a variable is changed.
My code :
import tkinter as tk
import time
root = tk.Tk()
root.resizable(width=False, height=False)
w = 800 # width for the Tk root
h = 500 # height for the Tk root
ws = root.winfo_screenwidth() # width of the screen
hs = root.winfo_screenheight() # height of the screen
x = (ws/2) - (w/2)
y = (hs/2) - (h/2)
root.geometry('%dx%d+%d+%d' % (w, h, x, y))
wheat=10
money=0
title=tk.Label(root, text="The Farm Game")
title.config(font=('times', 20, 'bold'))
title.place(height=30, width=300, x = 250 , y = 10)
def advance():
moneyguidisplay = tk.StringVar()
moneyshowed = ("£", money)
moneyguidisplay.set(moneyshowed)
moneygui = tk.Label(root, wraplength=200, textvariable=moneyguidisplay)
moneygui.config(bg='lightgreen', font=('times', 15, 'bold'))
moneygui.place(height=30, width=200, x=600, y=60)
Usershow = tk.StringVar()
shownow = ("Welcome to The farm game")
Usershow.set(shownow)
USER = tk.Label(root, wraplength=200, textvariable=Usershow)
USER.config(bg='lightpink', font=('times', 15, 'bold'))
USER.place(height=200, width=400, x=200, y=100)
wheatguidisplay = tk.StringVar()
wheatshowed = ("Wheat:", wheat)
wheatguidisplay.set(wheatshowed)
Wheatgui = tk.Label(root, wraplength=200, textvariable=wheatguidisplay)
Wheatgui.config(bg='lightblue', font=('times', 15, 'bold'))
Wheatgui.place(height=30, width=200, x=0, y=60)
root.after(100, advance)
root.after(100, advance)
root.mainloop()
Your question is a little unclear, but what I can understand is that you want to be able to change the text of a Label, depending on the value of another variable(correct me if I'm wrong). You can use the config method to do so. I have written a small function for it, you can put it in your program.
from tkinter import*
root=Tk()
L=Label(text="Label text changing after 5 sec")
L.grid()
# Call this function where the value of your variable/number changes
def ChangeValue(num):
L.config(text=str(num))
print("Value Changed")
root.update()
root.after(5000,lambda :ChangeValue("Text Changed!"))
root.mainloop()
I'm creating a simple madlib style game and I've come into a bit of a problem. I cannot get the canvas to clear and show the results.
The following code places an image as the background of a canvas. It then places labels and entry fields in 2 columns for all of the words to be inserted. There is a submit button at the bottom of the page. I can't figure out how to get it clear everything except the background image, so that it can display the story, with the users words inserted. If i place it in the callback(), it clears just the background and keeps everything else. I want the opposite.
from tkinter import *
from PIL import Image, ImageTk
canvas_width = 360
canvas_height = 525
file = r"C:\Users\kraak\Desktop\PyCharm Community Edition 2017.1.2\borderedpaper.GIF"
master = Tk()
canvas = Canvas(master, width=canvas_width, height=canvas_height)
old_img = PhotoImage(file=file)
new_img = old_img.subsample(3, 3)
canvas.create_image(-11, -10, anchor=NW, image=new_img)
canvas.create_window(0, 0, height=1, width=1, anchor=NW)
canvas.create_text(0, 0, text="Test")
e1 = Entry(canvas)
canvas.create_window(250, 60, window=e1, height=15, width=100)
label = Label(text="Enter an adjective.")
label.place(x=40, y=50)
e1.focus_set()
e2 = Entry(canvas)
canvas.create_window(250, 85, window=e2, height=15, width=100)
label = Label(text="Enter a nationality.")
label.place(x=40, y=75)
e2.focus_set()
def callback():
print("Pizza was invented by a " + (e1.get()) + " " + (e2.get()))
def answer():
button = Button(text="Submit.", command=callback)
button.place(x=150, y=460)
answer()
canvas.pack()
mainloop()
As Bryan Oakley suggested you can store the id's of the widgets you want to get rid of in a list to make it easier to destroy() them all in the callback() function. Here's showing the modification to your code that would do that—note the lines with a # ADDED comments.
from tkinter import *
from PIL import Image, ImageTk
canvas_width = 360
canvas_height = 525
file = r"C:\Users\kraak\Desktop\PyCharm Community Edition 2017.1.2\borderedpaper.GIF"
master = Tk()
canvas = Canvas(master, width=canvas_width, height=canvas_height)
canvas_entry_widgets = [] # ADDED
old_img = PhotoImage(file=file)
new_img = old_img.subsample(3, 3)
canvas.create_image(-11, -10, anchor=NW, image=new_img)
canvas.create_window(0, 0, height=1, width=1, anchor=NW)
canvas.create_text(0, 0, text="Test")
e1 = Entry(canvas)
canvas.create_window(250, 60, window=e1, height=15, width=100)
label = Label(text="Enter an adjective.")
label.place(x=40, y=50)
e1.focus_set()
canvas_entry_widgets.append(e1) # ADDED
e2 = Entry(canvas)
canvas.create_window(250, 85, window=e2, height=15, width=100)
label = Label(text="Enter a nationality.")
label.place(x=40, y=75)
e2.focus_set()
canvas_entry_widgets.append(e2) # ADDED
def callback():
print("Pizza was invented by a " + (e1.get()) + " " + (e2.get()))
# destroy the canvas entry widgets and clear the list # ADDED
while canvas_entry_widgets: # ADDED
widget = canvas_entry_widgets.pop() # ADDED
widget.destroy() # ADDED
def answer():
button = Button(text="Submit.", command=callback)
button.place(x=150, y=460)
answer()
canvas.pack()
mainloop()
Every widget has a destroy method which can be used to delete the widget. In your callback you can simply call this method for every widget:
def callback():
e1.destroy()
e2.destroy()
...
In your specific case, if you want to delete all the labels you will have to give them unique names. Or, to make this even easier, you can store all of your widgets and iterate over the list.