How to make a Tkinter frame raise from different files? - python

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?

Related

What is the problem of the sidebar and how to fix it?

I'm trying to make sidebar with <Enter> and <Leave> binding and if I move my mouse slower everything works fine, but if I go faster with my mouse the sidebar starts to move back and forth without stopping. Is there a way to fix it?
(Im new with tkinter and python in general)
1/2
2/2
from tkinter import *
#MainWindow
def MainWindow():
global WindowMain
WindowMain = Tk()
WindowMain.config(background="LightGray")
WindowMain.overrideredirect(1)
#MainWindow_size
def Screen_size():
app_width = 1280
app_height = 720
screen_width = WindowMain.winfo_screenwidth()
screen_height = WindowMain.winfo_screenheight()
x = (screen_width / 2) - (app_width / 2)
y = (screen_height / 2) - (app_height / 2)
WindowMain.geometry(f'{app_width}x{app_height}+{int(x)}+{int(y)}')
#Func1
def close(e):
for x in range(1000, 1200):
Blue.place(x=x, y=0)
DarkBlue.place(x=x, y=0)
Blue.update()
DarkBlue.update()
Blue.bind("<Enter>", open)
#Func2
def open(e):
for x in range(-1200, -1000):
Blue.place(x=-x, y=0)
DarkBlue.place(x=-x, y=0)
Blue.update()
DarkBlue.update()
Blue.bind("<Leave>", close)
MainWindow()
Screen_size()
#Label1&2
Blue = Label(WindowMain, background="DeepSkyBlue",
width=70, height=50)
DarkBlue = Label(WindowMain, width=2, height=100,
background="DodgerBlue")
Blue.place(x=1200)
DarkBlue.place(x=1200)
#Buttons
Quit = Button(WindowMain, text="Quit", command=quit,
background="LightSkyBlue").pack()
Move = Button(WindowMain, text="open", command=open,
background="LightSkyBlue", state=DISABLED).pack()
Undo = Button(WindowMain, text="close", command=close,
background="LightSkyBlue", state=DISABLED).pack()
Blue.bind("<Enter>", open)
WindowMain.mainloop()
Your problem will be solved.
I just play around with Blue.update() and Blue.bind. See line
31-31 and 40-41.
In line 31-31 and 40-41, should be outside of looping.
Do not used keyword open and close. Those are valid for Python 3
Modified code:
from tkinter import *
#MainWindow
#def MainWindow():
#global WindowMain
WindowMain = Tk()
WindowMain.config(background="LightGray")
#WindowMain.overrideredirect(1)
#MainWindow_size
def Screen_size():
app_width = 1280
app_height = 720
screen_width = WindowMain.winfo_screenwidth()
screen_height = WindowMain.winfo_screenheight()
x = (screen_width / 2) - (app_width / 2)
y = (screen_height / 2) - (app_height / 2)
WindowMain.geometry(f'{app_width}x{app_height}+{int(x)}+{int(y)}')
#Func1
def _close(e):
for x in range(1000, 1200):
Blue.place(x=x, y=0)
DarkBlue.place(x=x, y=0)
Blue.update()
Blue.bind("<Enter>", _open)
#Func2
def _open(e):
for x in range(-1200, -1000):
Blue.place(x=-x, y=0)
DarkBlue.place(x=-x, y=0)
Blue.update()
Blue.bind("<Leave>", _close)
Screen_size()
#Label1&2
Blue = Label(WindowMain, background="DeepSkyBlue",
width=70, height=50)
DarkBlue = Label(WindowMain,width=2, height=100,
background="DodgerBlue")
Blue.place(x=1200)
DarkBlue.place(x=1200)
#Buttons
Quit = Button(WindowMain, text="Quit", command=quit,
background="LightSkyBlue").pack()
Move = Button(WindowMain, text="open", command=_open,
background="LightSkyBlue", state=DISABLED).pack()
Undo = Button(WindowMain, text="close", command=_close,
background="LightSkyBlue", state=DISABLED).pack()
Blue.bind("<Enter>", _open)
WindowMain.mainloop()
Screenshot before mouse moved:
Screenshot After mouse moved:

Displaying frames in TKinter without classes

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

Getting current value when dragging canvas

I am trying to make a simple card game, something like Solitaire.
I am not experienced in coding, so forgive me if it's a simple question.
I want to move some canvas objects. New objects have the right value, but when i am dragging an already existing card it shows the wrong value (waarde in Dutch). I would like to bind the value (waarde) to a card, but don't know how to do that...
Thought about tags, binding, ID....
from tkinter import *
from random import randint
window = Tk()
deck = [1,2,3,4,5,6]
def pakkaart():
rand_card = randint(0,len(deck)-1)
global waarde
waarde = deck[rand_card]
deck.pop(rand_card)
global kaart
kaart = Canvas(window, width = 40, height = 40, bg='yellow')
kaart.place(x=50, y=50, anchor=CENTER)
kaart.create_text(20,20,text=(waarde))
kaart.bind("<B1-Motion>", drag)
def drag(event):
event.widget.place(x=event.x_root, y=event.y_root,anchor=CENTER)
print(waarde)
button1 = Button(window, text="Nieuwe Kaart", command=pakkaart)
button1.pack()
window.mainloop()
So essentially looking for a way to bind a value to a canvas.
Your above code works fine, it shows the correct value, but if you want you can try this
from tkinter import *
from random import randint
window = Tk()
ws = window.winfo_screenwidth()
hs = window.winfo_screenheight()
w = 500 # width for the Tk root
h = 300 # height for the Tk root
x = (ws / 2) - (w / 2)
y = (hs / 2) - (h / 2)
window.geometry('%dx%d+%d+%d' % (w, h, x, y))
deck = [1, 2, 3, 4, 5, 6]
def pick_card():
global waarde, kaart
rand_card = randint(0, len(deck)-1)
card_number = deck[rand_card]
deck.remove(card_number)
card = Canvas(window, width=40, height=40, bg='yellow')
card.place(x=50, y=50, anchor=CENTER)
card_number_text = card.create_text(20, 20, text=card_number, tags=card_number)
card.bind("<Button-1>", lambda event: get_number(event, card_number_text)) # or you can use: card.bind("<Button-1>", lambda event: print(card_number))
card.bind("<B1-Motion>", drag)
def drag(event):
# This is better for move a widget
cx = window.winfo_pointerx() - window.winfo_rootx()
cy = window.winfo_pointery() - window.winfo_rooty()
event.widget.place(x=cx, y=cy)
def get_number(event, number):
print(event.widget.itemcget(number, "text"))
button1 = Button(window, text="Generate Card", command=pick_card)
button1.pack()
window.mainloop()
I've modified the drag(event) function and wrote two ways for get the current card value, for store it you can use some global varibles or create a class, the second would be better

How to insert a picture into the splash screen?

I just want to know how could I insert a picture into the splash screen?
from tkinter import *
#splash screen
class SplashScreen(Frame):
def __init__(self, master=None, width=0.8, height=0.6, useFactor=True):
Frame.__init__(self, master)
self.pack(side=TOP, fill=BOTH, expand=YES)
# get screen width and height
ws = self.master.winfo_screenwidth()
hs = self.master.winfo_screenheight()
w = (useFactor and ws * width) or width
h = (useFactor and ws * height) or height
# calculate position x, y
x = (ws / 2) - (w / 2)
y = (hs / 2) - (h / 2)
self.master.geometry('%dx%d+%d+%d' % (w, h, x, y))
self.master.overrideredirect(True)
self.lift()
if __name__ == '__main__':
root = Tk()
sp = SplashScreen(root)
sp.config(bg="#3632ff")
m = Label(sp, text="MH60 NAVIGATION APP")
m.pack(side=TOP, expand=YES)
m.config(bg="#3366ff", justify=CENTER, font=("calibri", 29))
Button(sp, text="PRESS TO START", bg='red', command=root.destroy).pack(side=BOTTOM, fill=X)
root.mainloop()
Just add some widget with an image to your SplashScreen instance. For example, say your splash screen image was this .gif:
Then adding it to your code would look something like this (via a Button widget):
from tkinter import *
class SplashScreen(Frame):
def __init__(self, master=None, width=0.8, height=0.6, useFactor=True):
Frame.__init__(self, master)
self.pack(side=TOP, fill=BOTH, expand=YES)
# Add widget with the splash screen image on it.
self.img = PhotoImage(file='splash.gif')
btn = Button(self, image=self.img)
btn.pack(expand=YES, ipadx=10, ipady=10)
# get screen width and height
ws = self.master.winfo_screenwidth()
hs = self.master.winfo_screenheight()
w = (useFactor and ws * width) or width
h = (useFactor and ws * height) or height
# calculate position x, y
x = (ws / 2) - (w / 2)
y = (hs / 2) - (h / 2)
self.master.geometry('%dx%d+%d+%d' % (w, h, x, y))
self.master.overrideredirect(True)
self.lift()
if __name__ == '__main__':
root = Tk()
sp = SplashScreen(root)
sp.config(bg="#3632ff")
m = Label(sp, text="MH60 NAVIGATION APP")
m.pack(side=TOP, expand=YES)
m.config(bg="#3366ff", justify=CENTER, font=("calibri", 29))
Button(sp, text="PRESS TO START", bg='red', command=root.destroy).pack(side=BOTTOM, fill=X)
root.mainloop()
This is how it looks running on my system:
Step 1:- Import Module.
Step 2:- Create splash screen.
step 3:- Set title and geometry for splash screen.
step 4:- Insert photo file name to be display.
step 5:- Create Label and Pack the Label.
# Import Module
from tkinter import *
splash = Tk()
splash.title("Welcome") # assigning title for splash screen
splash.geometry("800x750+300+100") # set geometry for splash screen
splash.after(4000, splash.destroy) # splash screen will destroy after 4 sec
bg = PhotoImage(file = "file_name.png") # insert file name to be display
lab = Label(splash, image = bg) # create label
lab.pack() # pack the label
splash.mainloop()
bg = PhotoImage(file = "file_name.png") # insert file name to be display
file_name(photo) should be present(save) in folder where above code is saved.
If file_name is not given in code or the image does not exist in folder where above code is saved then the error will appear while running code.
Error:-
_tkinter.TclError: couldn't open "file_name.png": no such file or directory
Probably you are trying to use jpg or other type of file, like jpeg..., check this or change the type of file to png.

Python RawTurtle not following goto() command

I am trying to create a program where you click on a Tkinter canvas and a RawTurtle moves to the mouse, but my code is not working. The canvas has a Button-1 event binded to it to tell the program the coordinates of the mouse.
But, when you click on the canvas, instead of the turtle going to the mouse, it kind of mirrors what you would expect it to do (moves away from the mosue as if another mosue is being mirrored). Both the event and the turtle position coordinates are the same when they are printed out.
Code:
import turtle
from tkinter import *
def move(event):
global t
x = event.x
y = event.y
t.setpos(x,y)
print(t.pos())
print(event)
def penState(event):
global penDown,t
if penDown == True:
t.penup()
penDown = False
else:
t.pendown()
penDown = True
def changeWidth(w):
t.pensize(w)
def changeColour(e=None):
global colourBox
t.color(colourBox.get())
colourBox.configure(fg=colourBox.get())
def doCircle():
global checkFillIsTrue,circleSizeBox
if checkFillIsTrue.get() == 1:
begin_fill()
t.circle(int(circleSizeBox.get()))
end_fill()
else:
circle(int(circleSizeBox.get()))
window = Tk('Paint')
window.title('onionPaint')
root = Frame(window)
root.pack(side=LEFT)
cv = Canvas(window,width=500,height=500)
t = turtle.RawTurtle(cv)
t.resizemode('user')
cv.bind('<Button-1>',move)
cv.bind('<Button-2>',penState)
cv.pack(side=RIGHT)
checkFillIsTrue=IntVar()
penDown = True
#Pen width box
sizeLabel = Label(root, text="Pen Width")
sizeLabel.grid()
sizeScale = Scale( root, variable = \
'var',orient=HORIZONTAL,command=changeWidth )
sizeScale.grid()
#Colour box
colourLabel = Label(root, text="Color(HEX or name):")
colourLabel.grid()
colourFrame = Frame(root)
colourFrame.grid()
colourBox = Entry(colourFrame, bd=1)
colourBox.pack(side=LEFT)
colourSubmit = Button(colourFrame,text="OK",command=changeColour)
colourSubmit.pack(side=RIGHT)
#Fill
fillLabel = Label(root,text='Fill')
fillLabel.grid()
fillFrame = Frame(root)
fillFrame.grid()
beginFill = Button(fillFrame,text='Begin Fill',command=t.begin_fill)
endFill = Button(fillFrame,text='End Fill',command=t.end_fill)
beginFill.pack(side=LEFT)
endFill.pack(side=RIGHT)
#Mmore shapes
Label(root,text='Shapes').grid()
#Circle form
Label(root,text='Circle',font=('Heveltica',8)).grid()
circleSize = Frame(root)
circleSize.grid()
circleSizeBox = Entry(circleSize,bd=1)
circleSizeBox.insert(0,'Radius')
circleSizeBox.pack(side=LEFT)
fillCheck =
Checkbutton(circleSize,text='Fill',variable=checkFillIsTrue).pack(side=LEFT)
circleSizeSubmit =
Button(circleSize,text='Draw',command=doCircle).pack(side=RIGHT)
#Text form
Label(root,text='Text',font=('Heveltica',8)).grid()
textFrame = Frame(root)
textFrame.grid()
window.mainloop()
Any help with this problem would be greatly appreciated.
Your code is a disaster. You should specifically read up on the 'global' keyword in Python and when it must be used. And Python code style in general. I believe the key fix to your program is to introduce a TurtleScreen overlay on the canvas and then switch to turtle event handing rather than tkinter event handing.
I've reworked your code below, fixing as many problems as I could:
import turtle
from tkinter import *
FONT = ('Helvetica', 8)
def move(x, y):
terrapin.setpos(x, y)
print(terrapin.pos())
def penState(x, y):
global penDown
if penDown:
terrapin.penup()
penDown = False
else:
terrapin.pendown()
penDown = True
def changeWidth(w):
terrapin.pensize(w)
def changeColour():
color = colourBox.get()
terrapin.color(color)
colourBox.configure(fg=color)
def doCircle():
radius = int(circleSizeBox.get())
if checkFillIsTrue.get():
terrapin.begin_fill()
terrapin.circle(radius)
terrapin.end_fill()
else:
terrapin.circle(radius)
window = Tk('Paint')
window.title('onionPaint')
root = Frame(window)
root.pack(side=LEFT)
canvas = Canvas(window, width=500, height=500)
screen = turtle.TurtleScreen(canvas)
terrapin = turtle.RawTurtle(screen)
screen.onclick(move, btn=1)
screen.onclick(penState, btn=2)
canvas.pack(side=RIGHT)
checkFillIsTrue = BooleanVar()
penDown = True
# Pen width box
sizeLabel = Label(root, text="Pen Width")
sizeLabel.grid()
sizeScale = Scale(root, variable='var', orient=HORIZONTAL, command=changeWidth)
sizeScale.grid()
# Colour box
colourLabel = Label(root, text="Color(HEX or name):")
colourLabel.grid()
colourFrame = Frame(root)
colourFrame.grid()
colourBox = Entry(colourFrame, bd=1)
colourBox.pack(side=LEFT)
colourSubmit = Button(colourFrame, text="OK", command=changeColour)
colourSubmit.pack(side=RIGHT)
# Fill
fillLabel = Label(root, text='Fill')
fillLabel.grid()
fillFrame = Frame(root)
fillFrame.grid()
beginFill = Button(fillFrame, text='Begin Fill', command=terrapin.begin_fill)
endFill = Button(fillFrame, text='End Fill', command=terrapin.end_fill)
beginFill.pack(side=LEFT)
endFill.pack(side=RIGHT)
# More shapes
Label(root, text='Shapes').grid()
# Circle form
Label(root, text='Circle', font=FONT).grid()
circleSize = Frame(root)
circleSize.grid()
circleSizeBox = Entry(circleSize, bd=1)
circleSizeBox.insert(0, 'Radius')
circleSizeBox.pack(side=LEFT)
fillCheck = Checkbutton(circleSize, text='Fill', variable=checkFillIsTrue).pack(side=LEFT)
circleSizeSubmit = Button(circleSize, text='Draw', command=doCircle).pack(side=RIGHT)
# Text form
Label(root, text='Text', font=FONT).grid()
textFrame = Frame(root)
textFrame.grid()
window.mainloop()

Categories