今天我们将利用 tkinter
库制作以下的登录界面, 可以实现登录,并可以实现注册和登录,这里为了简单起见,使用 json
文件保存读取用户账号和密码
首先,我们需要建立一个根窗口,控制其不能够缩放并设置其标题,调用mainloop
方法来控制
from tkinter import *
window = Tk() # 建立根目录
window.title("Welcome") # 设置标题
window.geometry("500x400") # 设置窗口的大小
window.resizable(width=False, height=False) # 设置窗口不能够缩放
window.mainloop()
到此,我们运行一下,便可以得到如下的效果
然后我们来设置一下首页中图片,利用PIL
和Canvas
中的create_image
方法加上控制一下位置,我们便可以实现,代码如下:
from PIL import Image, ImageTk
# 首页的图片
image = Image.open("./welcome.jpg") # 打开图片,保存在image对象中
img = ImageTk.PhotoImage(image) # 转化成tkinter中的图片对象
c = Canvas(window, width=500, height=200) # 创建画布对象
c.create_image(250, 0, image=img, anchor=N) # 添加图片
c.pack() # 将图片打包到首页上
就这样就,我们实现了如下的效果
接下来我们就需要在上面添加文字信息,在tkinter
中提供了一个类Label
可以为我们做这件事,常见用法如下
Label(master[, text, font,textvariabel, wraplength, padx, pady, ...])
master
是要显示的窗口text
为要显示的文字font
为要显示的文字的字体,可以控制字体的大小textvariable
文字变量,以文字变量的值显示wraplength
换行的长度padx, pady
内容区与边界的距离知道了这些之后,我们便可以在之前的窗口上添加这些文字了,然后使用place
将这些控件摆放在对应的位置
username_label = Label(window, font='Monaco 12', text="username:")
passwd_label = Label(window, font='Monaco 12', text='password:')
username_label.place(x=40, y=220) # 摆放位置
passwd_label.place(x=40, y=260)
welcome = Label(window, font="monaco 12", text='Welcome here to learn python !')
welcome.place(x=250, y=320, anchor=N)
那么输入框如何解决呢,在tkinter
中提供了Entry
控件可以获取用户的输入,用法见下:
Entry(master, [textvariable, width, show, font, padx, pady, ...])
master
是要显示的窗口show
为输入显示的字符,默认为None,即显示原字符font
为要显示的文字的字体,可以控制字体的大小textvariable
文字变量,输入的值可以保存在该变量之中width
输入框的宽度padx, pady
内容区与边界的距离在tkinter
中有定义好的变量类型对象 – BooleanVar
, DoubleVar
, IntVar
, StringVar
分别可以保存布尔类型,浮点数类型,整数类型以及字符串类型的变量,使用的时候,我们可以使用其中的set
方法来赋值,使用get
方法来获取其中的值,使用这些变量通常会在交互中需要改变某个变量的值,比如输入,选择等
知道了以上这些之后,我们便可以用来实现处理用户输入了,代码如下:
# 输入框
username = StringVar()
passwd = StringVar()
# 以下将用户输入的内容赋值给我们的变量
username_entry = Entry(window, font='Monaco 10', width=20, textvariable=username)
passwd_entry = Entry(window, font='Monaco 10', width=20, textvariable=passwd, show='*')
username_entry.place(x=150, y=225)
passwd_entry.place(x=150, y=265)
做到这里,效果已经出来了,我们还需要添加两个按钮来实现登录和注册,在tkinter
中Button
可以为我们服务,使用方法如下:
Button(master [, text, font, command, width, borderwidth...])
master
是要显示的窗口text
为要显示的文字font
为要显示的文字的字体,可以控制字体的大小command
为点击之后执行的函数width
为按钮的宽度borderwidth
为边框的宽度于是,我们可以使用这样的代码来添加我们的按钮
login_button = Button(window, width=8, text='Login in', font='Monaco 10', borderwidth=1, command=None)
sign_up_buttom = Button(window, width=8, text='Sign up', font='Monaco 10', borderwidth=1, command=None)
login_button.place(x=360, y=260)
sign_up_buttom.place(x=360, y=220)
做到这里,图形的界面已经快完成了,效果如下
接下来我们需要具体的实现其功能,首先我们来实现注册功能
注册的时候,我们应该再弹出一个小窗来负责这一部分,在tkinter
中提供了Toplevel
对象可以帮我们实现,Toplevel
对象就类似与Tk
一样,是一个相对独立,拥有和Tk
一样结构的窗口,所以首先我们可以和之前一样来设置一下这个弹窗的属性,并对其进行添加其他控件
# 图片的定义,应该为全局变量
img_2 = Image.open("./sign_up.jpg")
img_2 = ImageTk.PhotoImage(img_2)
win = Toplevel() # 创建一个顶层窗口
win.resizable(width=False, height=False) # 设置窗口不能缩放
win.title("Sign up") # 设置标题
win.geometry('400x300') # 设置窗口的大小
win.wm_attributes('-topmost', -1) # 使得该窗口位于页面的最顶端
win_c = Canvas(win)
win_c.create_image(190, 150, image=img_2) # 绘制图片
win_c.pack() # 打包
prompt = Label(win, text='Cyberist -- a python learner', font='Monaco 8')
prompt.place(x=100, y=270)
# 提示信息 账号 密码 密码确认
user_label = Label(win, text='username:', font='monaco 10', bg=None)
pwd_label = Label(win, text='password:', font='monaco 10')
pwd_confirm_label = Label(win, text='confirm:', font='monaco 10')
# 摆放这些标签,放在合适的位置
user_label.place(x=20, y=180)
pwd_label.place(x=20, y=210)
pwd_confirm_label.place(x=20, y=240)
# 定义变量获取用户的输入信息
new_user = StringVar()
new_passwd = StringVar()
new_passwd_confirm = StringVar()
# 输入框选项设置
user_entry = Entry(win, font='Monaco 12', width=20, textvariable=new_user)
passwd_entry = Entry(win, font='Monaco 12', width=20, textvariable=new_passwd, show='*')
passwd_confirm_entry = Entry(win, font='Monaco 12', width=20, textvariable=new_passwd_confirm, show='*')
# 摆放好这些输入框的位置
user_entry.place(x=100, y=180)
passwd_entry.place(x=100, y=210)
passwd_confirm_entry.place(x=100, y=240)
# 根据之前在登录界面的用户名填写 uername为之前定义的变量,这里的代码只是为了简便用户的操作,
# 这样在操作的时候就不用输入之前的用户名来实现注册
tmp_username = username.get()
new_user.set(tmp_username)
# 定义按钮,设置位置
sign_up_button = Button(win, text='sign up', font='Monaco 10', command=write_in)
sign_up_button.place(x=310, y=210)
运行之后我们可以得到这样的效果,于是离我们的最终的效果又近了一步
定义好了这样的一个窗口,我们应该将其打包成一个函数,然后在用户点击注册的时候弹出这样的窗口,加入这样定义的函数名称为sign_up
,于是我们需要修改一下之前sign_up_button
的属性
sign_up_buttom = Button(window, width=8, text='Sign up', font='Monaco 10', borderwidth=1, command=sign_up) # 调用sign_up函数
这样只要我们一点击sign_up_button便可以弹出这个窗口,对于login_in按钮,我们需要对用户的输入进行判断,在已经注册号的用户中查找对应信息,如果没有找到账号,提示该用户没有注册,是否注册,如果密码输入错误,提示密码错误
在tkinter
中messagebox
可以帮我们提供许多信息弹窗:
showinfo
向用户显示信息showerror
显示错误showwarning
显示警告askquestion
向用户提问,可选择yes
或 no
的问题askokcancel
提示选择askyesno
提示选择askyesnocancel
提示选择askretrycancel
提示选择具体用法一致,可以使用下列参数
title
提示窗口的标题message
需要显示的信息icon
只能为messagebox
中定义好的error
, info
, question
, or warning
detail
详细的信息default
只能为messagebox
中定义的abort
, retry
, ignore
, ok
, cancel
, no
, oryes
, 部分窗口没有该参数, 如showinfo
, showerror
, showwarning
实例使用如下:
from tkinter import messagebox
# 显示信息一类
messagebox.showinfo(title='Python', message='Welcome here to learn python',icon=messagebox.INFO, detail='Created by Cyberist' )
messagebox.showerror(title='Error', message='Do not click me', icon=messagebox.ERROR, detail='Created by Cyberist')
messagebox.showwarning(title='Warning', message='You have made a bug, go and fix it', detail='Created by Cyberist', icon=messagebox.WARNING)
# 获取用户信息类
messagebox.askokcancel(title='Choice', message='Do you want to continue', icon=messagebox.INFO, detail='Created by Cyberist', default=messagebox.OK)
messagebox.askquestion(title='Question', message='Do you want to continue', icon=messagebox.QUESTION, detail='Created by Cyberist', default=messagebox.YES )
messagebox.askretrycancel(title='Ask', message='You network does not work properly, do you want to try again', detail="Created by Cyberist", default=messagebox.RETRY)
messagebox.askyesnocancel(title='Ask', message='Start to download this', default=messagebox.YES)
messagebox.askyesno(title='Choice', message='Do you want to install this app', default=messagebox.YES)
通过这些学习,那么我们可以实现登录的这个功能了,文件的操作
和异常处理
这个大家现在不用着急,之后会用教程详细讲解的,关于json
库,也会在小知识点中进行讲解,届时进行关注便可~
于是我们可以得到一下的代码:
# 提交登录功能实现
def login():
user = username.get() # 获取用户输入的账号密码
password = passwd.get()
if str(user) and str(password): # 如果不是空的,则进行查找,如果是空的,则提示填充输入框
try:
with open('./data.json', 'r') as file: # 打开保存用户的账号密码的文件
data = json.load(file) # 加载文件并保存为json类型
if user in data:
if password == data[user]:
# 账号密码对上,输入登录成功
messagebox.showinfo(title='Successfully', message="Login in susscessfully")
"""
登录成功后可以在这里进行操作, 这里便不添加其他的功能了
"""
else:
# 密码输入错误,提示
messagebox.showerror(title='Error', message='password is wrong')
else:
# flag 可以保存用户的操作信息,如果选择的yes,则flag为True
flag = messagebox.askyesno(title='sign up',
message='You have not signed up, do you want to sign up')
if flag:
# 如果是,则进行注册
sign_up()
else:
# 否则的话,退出
window.destroy()
except:
# 打开文件错误,重新打开,并输入默认的账号密码
with open('./data.json', 'w') as file:
admin = {"admin": "Cyberist"}
json.dump(admin, file)
else:
# 没有填充输入框,提示错误
messagebox.showerror(title="Error", message='Fill in all the blank')
之间我们还有一个sign_up
的功能需要实现, sign_up
的界面设计在之前就已经实现了,我们现在需要实现的便是如何具体的实现的功能,其实思路比较清晰, 首先我们需要获取用户的输入,判断两次输入的密码是否正确,如果正确保存信息,否则提示重新输入,具体代码如下, 我们将其定义为write_in
函数:
def write_in():
# 如果输入的不是空的
if str(new_passwd.get()) and str(new_user.get()) and str(new_passwd_confirm.get()):
if new_passwd_confirm.get() == new_passwd.get():
# 如果两次输入的密码正确,在进行之下操作
try:
file = open("./data.json", "r")
data = json.load(file)
file.close()
if str(new_user.get()) in data:
messagebox.showinfo(title='Error', message='The username has been signed')
else:
file_2 = open("./data.json", "r")
user = str(new_user.get())
passwd = new_passwd.get()
data[user] = passwd
with open('./data.json', 'w') as file_3:
json.dump(data, file_3)
messagebox.showinfo(message="Sign up finished", title='Successfully')
win.destroy()
except Exception as e:
pass
else:
messagebox.showerror(title='Error', message='The confirmed password is not right !')
else:
messagebox.showerror(title='Error', message='Fill in all the blank !')
然后我们只需要将该函数被sign_up按钮调用便可
sign_up_button = Button(win, text='sign up', font='Monaco 10', command=write_in) # 调用write_in函数
到这里,我们的功能实现便已经完成了,登录的功能也具体实现1了,但是其实这些代码还是可以改进的,比如不用json
格式来保存用户的账号密码信息,而是使用pickle
库,这样用户的账号密码不会以明文的形式暴露出来,提高其安全性。此外,我们还可以对我们的界面进行自定义的美化,你想如何做,便如何做。
另外在这里提供了其中图片的下载, 并对其中的图片进行了操作
import requests
import os
from PIL import Image
"""
下载相关的图片,并对图片进行缩放等操作
"""
def download(url):
response = requests.get(url)
return response.content
def get_image():
url1= 'https://marketplace.canva.com/MADeqzsTN80/1/screen_2x/canva-sign-up-username-password-log-in-MADeqzsTN80.jpg'
url2 = 'https://images.unsplash.com/photo-1460467820054-c87ab43e9b59?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1561&q=80'
if os.path.exists('welcome.jpg'):
os.remove("welcome.jpg")
if os.path.exists('sign-up.jpg'):
os.remove('sign-up.jpg')
content1 = download(url2)
content2 = download(url1)
with open('./welcome.jpg', 'wb') as file:
file.write(content1)
with open('./sign_up.jpg', 'wb') as file:
file.write(content2)
def change(img_path,width, height):
img = Image.open(img_path)
img.thumbnail((width, height), resample=Image.LANCZOS)
img.save( img_path)
change('welcome.jpg', 265,200)
change("sign_up.jpg", 500,333)
def main():
get_image()
当然是用tkinter
也只是做图形的一种方法,自己对前端也是比较感兴趣,之后可能推出更多的相关教程,敬请关注
完整代码请在公众号内回复关键词登录界面
即可以获取, 代码已进行包装 ↩︎