暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

图形界面化编程(下)

Golang学习杂记 2019-11-19
341

今天我们将利用 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
    , or yes
    , 部分窗口没有该参数, 如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函数 


到这里,我们的功能实现便已经完成了,登录的功能也具体实现了,但是其实这些代码还是可以改进的,比如不用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
也只是做图形的一种方法,自己对前端也是比较感兴趣,之后可能推出更多的相关教程,敬请关注


完整代码回复关键词登录界面即可以获取, 代码已进行包装




文章转载自Golang学习杂记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论