Python编程教程:用tkinter写个密码器

python内置的GUI编程tkinter小巧灵活,本文以密码码器示例,所有注册的用户皆会被持久化

流程

用户登录/注册,成功则提示欢迎语,不正确或密码错误有相应警告

Python编程教程:用tkinter写个密码器

不存在帐户则提醒注册,并回调子页面注册,需要密码确认,注册已存在用户会被提醒

Python编程教程:用tkinter写个密码器

Python编程教程:用tkinter写个密码器

Python编程教程:用tkinter写个密码器

Python编程教程:用tkinter写个密码器

结构

两个window窗口,一个负责主界面引入了背景图,一个子负责注册账号密码,ui以tk为后缀名。event为tk的事件回调,store以pickle字典序列化存储类,usrs.pickle为持久化存储

entry
│  event.py
│  login_tk.py
│  sign_up_tk.py
│  store.py
│  usrs.pickle
│
├─.vscode
│      settings.json
│
├─img
│      coffee.png
│      java_classLoader.gif
│      web_spring.png
│      yms3mhzsf22.jpg
│
└─__pycache__
        event.cpython-37.pyc
        login.cpython-37.pyc
        sign_up_tk.cpython-37.pyc
        store.cpython-37.pyc

入口UI

login_tk.py

from tkinter import *
from tkinter import ttk

from event import login
from sign_up_tk import usr_sign_up

"""
定义界面
"""

# 1. 根实例
root = Tk()
root.title("Wellcome to Login")
root.geometry('400x350')

# 2.加载图片
canvas = Canvas(root, width=400, height=150, bg='green')
image_file = PhotoImage(file='img/coffee.png')
image = canvas.create_image(200, 0, anchor='n', image=image_file)
# 指定绘制方向
canvas.pack(side='top')
# 文本语录
ttk.Label(root, text='欢迎使用密码器', font=('Arial', 16)).pack()

# 3.用户静态文本
ttk.Label(root, text='用户:', font=('Arial', 14)).place(x=50, y=185)
ttk.Label(root, text='密码:', font=('Arial', 14)).place(x=50, y=215)

# 4.帐号输入变量
uname = StringVar()
uname.set('[email protected]')
ttk.Entry(root, textvariable=uname, font=('Arial', 14)).place(x=120, y=185)
# 5.密码输入
pwd = StringVar()
# 6.文本变量绑定参数
ttk.Entry(root, textvariable=pwd, font=(
    'Arial', 14), show='*').place(x=120, y=215)

# 7.事件回调使用变量
ttk.Button(root, text='登录', command=lambda: login(
    uname.get(), pwd.get())).place(x=120, y=270)

# 8. 注册加子页面
ttk.Button(root, text='注册', command=lambda: usr_sign_up(
    root)).place(x=250, y=270)


# 6.事件循环
root.mainloop()

注册UI

sign_up_tk.py

from tkinter import *
from tkinter import ttk
from event import sign_up_web


def usr_sign_up(root):
    # 定义在主窗口上的次窗口
    window_sign_up = Toplevel(root)
    window_sign_up.geometry('300x200')
    window_sign_up.title('注册')

    # 用户名
    uname = StringVar()
    uname.set('[email protected]')
    ttk.Label(window_sign_up, text="用户名:").place(x=10, y=10)
    ttk.Entry(window_sign_up, textvariable=uname).place(x=130, y=10)

    # 密码
    new_pwd = StringVar()
    ttk.Label(window_sign_up, text='密码: ').place(x=10, y=50)
    ttk.Entry(window_sign_up, textvariable=new_pwd,
              show='*').place(x=130, y=50)

    # 密码确认
    new_pwd_confirm = StringVar()
    ttk.Label(window_sign_up, text='重复密码: ').place(x=10, y=90)
    ttk.Entry(window_sign_up, textvariable=new_pwd_confirm,
              show='*').place(x=130, y=90)

    # 确认注册
    btn_comfirm_sign_up = ttk.Button(
        window_sign_up, text='注册', command=lambda: sign_up_web(new_pwd.get(), new_pwd_confirm.get(), uname.get(), window_sign_up)).place(x=180, y=120)

事件回调

event.py

from tkinter import *
from tkinter import ttk
import tkinter.messagebox as msgbox

from store import Store

"""
回调事件模块
"""


def login(uname, pwd):
    usrs_info = Store()._usrs
    if uname in usrs_info:
        if pwd == usrs_info[uname]:
            msgbox.showinfo(
                title="欢迎您", message='您还好吗? ' + uname)
        else:
            msgbox.showerror(
                message='错误! 密码不正确, 请重试.')
    else:
        msgbox.askyesno(
            '欢迎 '+uname, '你还没有注册,请先注册')



def sign_up_web(pwd,confirm,uname,window_sign_up):
    db = Store()
    if pwd != confirm:
        print(pwd,confirm)
        msgbox.showerror(
            '错误', '两次输入的密码不一致!')
    elif uname in db._usrs:
        msgbox.showerror('警告', '该用户已经注册过!')
    else:
        # 注册新用户
        db.add(uname,pwd).save()
        msgbox.showinfo(
            '欢迎'+uname, '您已经注册成功!')
        # 销毁注册窗口
        window_sign_up.destroy()

存储类

import pickle

"""
数据存储模块
"""

class Store:
    def __init__(self, db="usrs.pickle"):
        self._db = db
        self._usrs = self._read()

    def _read(self):
        try:
            # 反序列化对象
            with open(self._db, 'rb') as f:
                self._usrs = pickle.load(f)
        except FileNotFoundError:
            # 序列化对象
            with open(self._db, 'wb') as f:
                # 默认内置管理员
                self._usrs = {'admin': '123456'}
                # 持久化写入文件
                pickle.dump(self._usrs, f)
        return self._usrs

    # 持久化
    def save(self):
        with open(self._db, 'wb') as f:
            pickle.dump(self._usrs, f)
            f.close()
    
    # 添加新用户
    def add(self, uname, pwd):
        self._usrs[uname] = pwd
        return self

    def show(self):
        print(self._usrs)


db = Store()
# db.add("zhansang","654321")
# db.save()
db.show()

其它

tk图像类只支持gif及png等有限图片,布局管理支持相对定位(pack自动计算),坐标系place,grid栅格系统