zoukankan      html  css  js  c++  java
  • Python初学——窗口视窗Tkinter

    此篇文章是跟着沫凡小哥的视频学习的,附上学习网址:https://morvanzhou.github.io/tutorials/python-basic/

    什么是 tkinter 窗口

    1.1 什么是 Tkinter

    Python自带的可编辑的GUI界面,是一个图像窗口。

    Tkinter是使用 python 进行窗口视窗设计的模块。简单的构造,多平台,多系统的兼容性, 能让它成为让你快速入门定制窗口文件的好助手。它在 python 窗口视窗模块中是一款简单型的。所以用来入门,熟悉窗口视窗的使用,非常有必要。

    tkinter 的窗口部件

    2.1 Label & Button 标签和按钮

    窗口主体框架

    每一个tkinter应用的主体框架都可以包含下面这部分,定义window窗口和window的一些属性,然后书写窗口内容,最后执行window.mainloop让窗口活起来。

    import tkinter as tk
    
    window = tk.Tk()
    window.title('my window')
    window.geometry('300x100')
    
    # 这里是窗口的内容
    
    window.mainloop()

    首先建立一个用来描述的标签tk.Label(注意对象的首字母一般是大写),示例代码如下所示:

    l = tk.Label(window, 
        text='OMG! this is TK!',    # 标签的文字
        bg='green',     # 背景颜色
        font=('Arial', 12),     # 字体和字体大小
        width=15, height=2)  # 标签长宽
    l.pack()    # 固定窗口位置

    运行结果如图所示:

    我们也可以通过变量的形式控制标签的显示,这时我们引入按钮 tk.Button 的概念,每点一次按钮,标签变化一次。 用以下内容替换上面的标签. 并把需要变化的文字存成变量 var:

    var = tk.StringVar()    # 这时文字变量储存器
    l = tk.Label(window, 
        textvariable=var,   # 使用 textvariable 替换 text, 因为这个可以变化
        bg='green', font=('Arial', 12), width=15, height=2)
    l.pack() 

    接着做按钮tk.Button:

    b = tk.Button(window, 
        text='hit me',      # 显示在按钮上的文字
        width=15, height=2, 
        command=hit_me)     # 点击按钮式执行的命令
    b.pack()    # 按钮位置

    hit_me函数如下:

    on_hit = False  # 默认初始状态为 False
    def hit_me():
        global on_hit
        if on_hit == False:     # 从 False 状态变成 True 状态
            on_hit = True
            var.set('you hit me')   # 设置标签的文字为 'you hit me'
        else:       # 从 True 状态变成 False 状态
            on_hit = False
            var.set('') # 设置文字为空

    运行结果如下所示:

    没有点击动作时:

    点击第一次:

    点击第二次:

    完整代码:

    import tkinter as tk
    
    window=tk.Tk()
    window.title('my window')
    window.geometry('300x100')
    
    var=tk.StringVar()
    l=tk.Label(window,textvariable=var,bg='green',font=('Arial',12),width=15,
               height=2)
    l.pack()
    
    on_hit=False
    
    def hit_me():
        global on_hit
        if on_hit==False:
            on_hit=True
            var.set('you hit me')
        else:
            on_hit=False
            var.set('')
    
    b=tk.Button(window,text='hit me',width=15,
                height=2,command=hit_me)
    b.pack()
        
    window.mainloop()

    2.2 Entry & Text 输入, 文本框

     在定义了窗口的基础上,首先定义一个Entry,代码如下所示:

    e = tk.Entry(window,show=None)
    e.pack()

    注意这里的show,可以自定义显示你想要在Entry中显示的字符,例如像输入密码时,可令show=‘*’

    本节实现的例子功能为,如下所示的一个窗口,从上至下分别为定义的Entry、Button、Button和Text。两个Button分别命名为insert point和insert end,获取Entry中输入的内容并且分别在光标位置、末尾插入,内容显示在Text中。

    Button的定义如下所示:

    b1 = tk.Button(window,text='insert point',width=15,
                height=2,command=insert_point)
    b1.pack()
    b2 = tk.Button(window,text='insert end',
                   command=insert_end)

    函数的定义如下所示:

    def insert_point():
        var = e.get()
        t.insert('insert',var)
    
    def insert_end():
        var = e.get()
        t.insert('end',var)


    完整代码如下:

    import tkinter as tk
    
    window = tk.Tk()
    window.title('my window')
    window.geometry('300x300')
    e = tk.Entry(window,show=None)
    e.pack()
    
    def insert_point():
        var = e.get()
        t.insert('insert',var)
    
    def insert_end():
        var = e.get()
        t.insert('end',var)
    b1 = tk.Button(window,text='insert point',width=15,
                height=2,command=insert_point)
    b1.pack()
    b2 = tk.Button(window,text='insert end',
                   command=insert_end)
    b2.pack()
    t = tk.Text(window,height=2)
    t.pack()
    
    window.mainloop()

     运行结果如下所示,首先在Entry中输入111111,点击按钮1,如下:

    选择某一点作为插入位置,再在Entry中输入2,点击按钮1

    在Entry中输入3,点击按钮2

    此外,insert还能实现具体位置的内容插入,例如将inser_end函数更改如下:

    def insert_end():
        var = e.get()
        t.insert(2.2,var)

    则insert_end实现在Text的2行2列出插入内容,运行结果如下所示:

    2.3 Listbox 列表部件

    本节例子实现功能为:如下所示,从上到下分别为Label、Button和Listbox,Button实现将Listbox中当前光标选中的内容显示在Label中。

     

    在定义好窗口的基础上首先定义Label,设置底色为黄色,并且要将文本内容定义为变量,代码如下:

    var1=tk.StringVar()
    l=tk.Label(window,bg='yellow',width=4,textvariable=var1)
    l.pack()

    接着定义Button,命名为‘print selection’,并定义command的函数,如下所示:

    def print_selection():
        value=lb.get(lb.curselection())
        var1.set(value)
        
    b1 = tk.Button(window, text='print selection', width=15,
                  height=2, command=print_selection)
    b1.pack()

    最后定义Listbox,如下所示实现了Listbox中内容的设置、插入、删除等。

    var2=tk.StringVar()
    var2.set((11,22,33,44))
    lb=tk.Listbox(window,listvariable=var2)
    list_items=[1,2,3,4]
    for item in list_items:
        lb.insert('end',item)
    lb.insert(1,'first')
    lb.insert(2,'second')
    lb.delete(2)
    lb.pack()

    完整代码如下所示:

    import tkinter as tk
    
    window = tk.Tk()
    window.title('my window')
    window.geometry('300x300')
    
    var1=tk.StringVar()
    l=tk.Label(window,bg='yellow',width=4,textvariable=var1)
    l.pack()
    
    def print_selection():
        value=lb.get(lb.curselection())
        var1.set(value)
        
    b1 = tk.Button(window, text='print selection', width=15,
                  height=2, command=print_selection)
    b1.pack()
    
    var2=tk.StringVar()
    var2.set((11,22,33,44))
    lb=tk.Listbox(window,listvariable=var2)
    list_items=[1,2,3,4]
    for item in list_items:
        lb.insert('end',item)
    lb.insert(1,'first')
    lb.insert(2,'second')
    lb.delete(2)
    lb.pack()

    window.mainloop()

    2.4 Radiobutton 选择按钮

    如图所示,Radiobutton即为上图中可选择的按钮,本节实现选中不同的Radiobutton时打印出相应的内容。

    首先定义底色为黄色的Label,代码见完整代码。

    接着要定义三个Radiobutton:

    r1=tk.Radiobutton(window,text='Option A',
                      variable=var,value='A',
                      command=print_selection)
    r1.pack()

     Radiobutton放在window上,命名为‘Option A’,其中var=tk.StringVar(),接着令按钮的variable等于var,并且赋值为‘A’。

    print_selection函数的定义如下:

    def print_selection():
        l.config(text='you have selected '+var.get())

    config能对所有的参数进行更改,在函数定义中选择text属性进行更改。

    完整代码如下:

    import tkinter as tk
    
    window = tk.Tk()
    window.title('my window')
    window.geometry('300x300')
    
    var=tk.StringVar()
    l=tk.Label(window,bg='yellow',width=20,text='empty')
    l.pack()
    
    def print_selection():
        l.config(text='you have selected '+var.get())
    
    r1=tk.Radiobutton(window,text='Option A',
                      variable=var,value='A',
                      command=print_selection)
    r1.pack()
    r2=tk.Radiobutton(window,text='Option B',
                      variable=var,value='B',
                      command=print_selection)
    r2.pack()
    r3=tk.Radiobutton(window,text='Option C',
                      variable=var,value='C',
                      command=print_selection)
    r3.pack()
    
    window.mainloop()

    运行结果如下所示,当未选中时,Label内容显示为empty,当选中某一个Radiobutton时,则Label中显示相应的内容

    2.5 Scale 尺度

     可以被拉动的一个条,Scale返回的是一个数字。如下所示,当拉动时会在Label上显示具体的数字。

     

    完整代码如下:

    import tkinter as tk
    
    window = tk.Tk()
    window.title('my window')
    window.geometry('300x300')
    
    l=tk.Label(window,bg='yellow',width=20,text='empty')
    l.pack()
    
    def print_selection(v):
        l.config(text='you have selected '+v)
    
    s=tk.Scale(window,label='try me',from_=5,to=11,orient=tk.HORIZONTAL,
               length=200,showvalue=0,tickinterval=3,resolution=0.01,command=print_selection)
    s.pack()
    
    window.mainloop()

    定义Scale的属性时,名字为label,from to为取值范围,from_是为了区分python中的from,Scale还有横向和竖向属性,注意为tk.横向/竖向。length为显示的长度,不同于Label中的width,width的单位是字符,和length的单位是像素。showvalue即是否显示所选中的数字,取值为0时不显示,为1时显示。显示的标签单位长度为tickinterval,即显示出的数字的间隔,取值为3时,即显示5,8,11。resolution为要保留的小数个数。

    在Scale中所定义的command功能是有默认传入值的,该传入值即为Scale标签当前标注的值。所以在定义print_selection函数时需要定义一个参数用于表示该传入值。

    2.6 Checkbutton 勾选项

    与Radiobutton类似,但是Radiobutton选中一个后其他默认为不选中,但是Checkbutton类似于多选,可以选中多个。

    定义两个Checkbutton,如下所示:

    var1=tk.IntVar()
    var2=tk.IntVar()
    c1=tk.Checkbutton(window,text='Python',variable=var1,onvalue=1,offvalue=0,
                      command=print_selection)
    c2=tk.Checkbutton(window,text='C++',variable=var2,onvalue=1,offvalue=0,
                      command=print_selection)
    c1.pack()
    c2.pack()

    首先定义两个变量var1和var2,为整型。

    两个Checkbutton的variable分别等于var1和var,并且选中时value为1,即onvalue=1,未选中时offvalue=0.

    command的print_selection定义如下,根据var1和var2的值来进行相应的操作。

    def print_selection():
        if(var1.get()==1)&(var2.get()==0):
            l.config(text='I love only Python')
        elif(var1.get()==0)&(var2.get()==1):
            l.config(text='I love only C++')
        elif(var1.get()==0)&(var2.get()==0):
            l.config(text='I do not love either')
        else:
            l.config(text='I love both')
            

    完整代码如下所示:

    import tkinter as tk
    
    window = tk.Tk()
    window.title('my window')
    window.geometry('300x300')
    
    l=tk.Label(window,bg='yellow',width=20,text='empty')
    l.pack()
    
    def print_selection():
        if(var1.get()==1)&(var2.get()==0):
            l.config(text='I love only Python')
        elif(var1.get()==0)&(var2.get()==1):
            l.config(text='I love only C++')
        elif(var1.get()==0)&(var2.get()==0):
            l.config(text='I do not love either')
        else:
            l.config(text='I love both')
            
        
    var1=tk.IntVar()
    var2=tk.IntVar()
    c1=tk.Checkbutton(window,text='Python',variable=var1,onvalue=1,offvalue=0,
                      command=print_selection)
    c2=tk.Checkbutton(window,text='C++',variable=var2,onvalue=1,offvalue=0,
                      command=print_selection)
    c1.pack()
    c2.pack()
    
    window.mainloop()

    运行结果如下所示:

    单独选中Python时:

    单独选中C++时:

    两个都选中:

    两个都不选:

    2.7 Canvas 画布

    规定一片区域,可以放置图片、图形等等,并且可以把位置和形状进行改变。

    import tkinter as tk
    
    window = tk.Tk()
    window.title('my window')
    window.geometry('300x300')
    
    canvas=tk.Canvas(window,bg='blue',height=150,width=200)
    image_file=tk.PhotoImage(file='3.png')
    image=canvas.create_image(10,10,anchor='nw',image=image_file)
    x0,y0,x1,y1=90,90,120,120
    line=canvas.create_line(x0,y0,x1,y1)
    oval=canvas.create_oval(x0,y0,x1,y1,fill='yellow')
    arc=canvas.create_arc(x0+30,y0+30,x1+30,y1+30,start=0,extent=180,fill='green')
    rect=canvas.create_rectangle(100,30,100+20,30+20)
    canvas.pack()
    
    def moveit():
        canvas.move(rect,0,2)
        
    b=tk.Button(window,text='move',command=moveit).pack()
    
    window.mainloop()

     首先定义一个Canvas。

    放置一张图片,首先读取读片并存入到image_file中,接着Canvas通过create.image将图片放置到画布上。注意10,10为放置的坐标,anchor意为锚点,即锚定的位置,可选择的属性如下所示:

    nw即为放置在左上角,图片最左上角的点放置的坐标应为所定义的10,10.

    接着create.line从坐标为(90,90)到(120,120)绘制一条直线。

    create.oval为绘制圆形,fill填充颜色。

    create.arc为绘制扇形,start和extent表示该扇形从0°到180°。

    create.rectangle为绘制一个正方形。

    此外,定义了一个button,该按钮的作用是每点击一次,rect对象,即为所绘制的正方形下移两格,moveit函数中0表示x方向的位移为0,2为y方向上的位移变化尺度。结果如下所示。

    单机move按钮,正方形的位置发生变化:

    2.8 Menubar 菜单

    菜单条,如下所示为本节将要完成的简单菜单条。 

     

    首先在窗口window上定义一个Menu

    menubar=tk.Menu(window)

    接着在menubar上创建File选项,首先同样定义一个Menu,此时的Menu是放置在menubar上的,并通过add_cascade(cascade:级联)放置在menubar上

    filemenu=tk.Menu(menubar,tearoff=0)
    menubar.add_cascade(label='File',menu=filemenu)

      接着如上图所示,在File选项中,增加New、Open、Save,分隔线、以及Exit

    filemenu.add_command(label='New',command=do_job)
    filemenu.add_command(label='Open',command=do_job)
    filemenu.add_command(label='Save',command=do_job)
    filemenu.add_separator()
    filemenu.add_command(label='Exit',command=window.quit)

    同理,增加Edit选项,代码详见完整代码

    接着,我们来创建File中的Submenu,如下图所示

    submenu=tk.Menu(filemenu)
    filemenu.add_cascade(label='Import',menu=submenu,underline=0)
    submenu.add_command(label='Submenu1',command=do_job)

     在代码中,do_job做了一个简单的显示功能,如下所示:

    counter=0
    def do_job():
        global counter
        l.config(text='do '+str(counter))
        counter+=1

    完整代码:

    import tkinter as tk
    
    window = tk.Tk()
    window.title('my window')
    window.geometry('300x300')
    
    l=tk.Label(window,text='',bg='yellow')
    l.pack()
    
    counter=0
    def do_job():
        global counter
        l.config(text='do '+str(counter))
        counter+=1
        
    menubar=tk.Menu(window)
    filemenu=tk.Menu(menubar,tearoff=0)
    menubar.add_cascade(label='File',menu=filemenu)
    filemenu.add_command(label='New',command=do_job)
    filemenu.add_command(label='Open',command=do_job)
    filemenu.add_command(label='Save',command=do_job)
    filemenu.add_separator()
    filemenu.add_command(label='Exit',command=window.quit)
    
    editmenu=tk.Menu(menubar,tearoff=0)
    menubar.add_cascade(label='Edit',menu=editmenu)
    editmenu.add_command(label='Cut',command=do_job)
    editmenu.add_command(label='Copy',command=do_job)
    editmenu.add_command(label='Paste',command=do_job)
    
    submenu=tk.Menu(filemenu)
    filemenu.add_cascade(label='Import',menu=submenu,underline=0)
    submenu.add_command(label='Submenu1',command=do_job)
    
    window.config(menu=menubar)
    
    window.mainloop() 

    2.9 Frame 框架

    底层框架,可以在上面放各种小部件

     

    import tkinter as tk
    
    window = tk.Tk()
    window.title('my window')
    window.geometry('300x300')
    
    tk.Label(window,text='on the window').pack()
    
    frm=tk.Frame(window)
    frm.pack()
    frm_l=tk.Frame(frm,)
    frm_r=tk.Frame(frm)
    frm_l.pack(side='left')
    frm_r.pack(side='right')
    
    tk.Label(frm_l,text='on the frm_l1').pack()
    tk.Label(frm_l,text='on the frm_l2').pack()
    tk.Label(frm_r,text='on the frm_r1').pack()
    
    window.mainloop() 

    首先定义一个主Frame,放在window上

    接着定义了第二层的两个Frame,分别放在主Frame的左右侧

    在左边的Frame上放置了两个标签,右边放了一个标签

    2.10 messagebox 弹窗

    在window的基础上定义一个Button

    tk.Button(window, text='hit me', command=hit_me).pack()

    如图所示:

    接着定义一个弹窗,在运行时出现错误

    AttributeError: module 'tkinter' has no attribute 'messagebox'

    试着加入import则可运行成功

    from tkinter import messagebox

    messagebox有多种功能,接下来将分别细述

    (1)showinfo

    tk.messagebox.showinfo(title='Hi', message='hahahaha')

     (2)showwarning

    tk.messagebox.showwarning(title='Hi', message='nononono')

    (3)showerror

    tk.messagebox.showerror(title='Hi', message='No!! never')

    (4)askquestion返回是字符串,即返回的是‘yes’或者‘no’,可通过print打印出来以更好的理解

    print(tk.messagebox.askquestion(title='Hi', message='hahahaha'))   # return 'yes' , 'no'

    选择是打印出的值为‘yes’

    根据return的值可进一步选择需要的操作

    if return==‘yes’

    (5)askyesno

    返回的是True或者False

    print(tk.messagebox.askyesno(title='Hi', message='hahahaha'))   # return True, False

    同样可根据返回的值来进一步操作。

    (6)asktrycancel

    print(tk.messagebox.asktrycancel(title='Hi', message='hahahaha'))   # return True, False

    但是不知道为什么运行时出现错误:AttributeError: module 'tkinter.messagebox' has no attribute 'asktrycancel'

    (7)askokcancel

    print(tk.messagebox.askokcancel(title='Hi', message='hahahaha'))   # return True, False

    (8)askyesnocancel

    print(tk.messagebox.askyesnocancel(title="Hi", message="haha"))     # return, True, False, None

    完整代码:

    import tkinter as tk
    
    window = tk.Tk()
    window.title('my window')
    window.geometry('200x200')
    
    def hit_me():
        #tk.messagebox.showinfo(title='Hi', message='hahahaha')
        #tk.messagebox.showwarning(title='Hi', message='nononono')
        #tk.messagebox.showerror(title='Hi', message='No!! never')
        #print(tk.messagebox.askquestion(title='Hi', message='hahahaha'))   # return 'yes' , 'no'
        #print(tk.messagebox.askyesno(title='Hi', message='hahahaha'))   # return True, False
        #print(tk.messagebox.asktrycancel(title='Hi', message='hahahaha'))   # return True, False
        #print(tk.messagebox.askokcancel(title='Hi', message='hahahaha'))   # return True, False
        print(tk.messagebox.askyesnocancel(title="Hi", message="haha"))     # return, True, False, None
    
    tk.Button(window, text='hit me', command=hit_me).pack()
    window.mainloop()

    2.11 pack grid place 放置位置

    (1)pack

     side属性来决定所放置的位置,共有top、bottom、left、right

    tk.Label(window,text='1').pack(side='top')
    tk.Label(window,text='1').pack(side='bottom')
    tk.Label(window,text='1').pack(side='left')t
    tk.Label(window,text='1').pack(side='right')

    (2)grid

    按照格点(方格的形式来放置)

    for i in range(4):
        for j in range(3):
            tk.Label(window,text=1).grid(row=i,column=j,padx=10,pady=10)

    无padx和pady时:

    其中padx、pady用于填充显示,padx和pady用于设置框架的外部填充显示,ipadx和ipady用于设置框架的内部显示。

    (3)place

    能精确放置到某一坐标处

    tk.Label(window,text=1).place(x=20,y=10,anchor='nw')

    登录窗口例子

    3.1 例子1 登录窗口

    综合前面所学习的内容,设计如下窗口

    代码如下所示:

    import tkinter as tk
    
    window = tk.Tk()
    window.title('Welcome to Mofan Python')
    window.geometry('450x300')
    
    # welcome image
    canvas = tk.Canvas(window, height=200, width=500)
    image_file = tk.PhotoImage(file='welcome.gif')
    image = canvas.create_image(0,0, anchor='nw', image=image_file)
    canvas.pack(side='top')
    
    # user information
    tk.Label(window, text='User name: ').place(x=50, y= 150)
    tk.Label(window, text='Password: ').place(x=50, y= 190)
    
    var_usr_name = tk.StringVar()
    var_usr_name.set('example@python.com')
    entry_usr_name = tk.Entry(window, textvariable=var_usr_name)
    entry_usr_name.place(x=160, y=150)
    var_usr_pwd = tk.StringVar()
    entry_usr_pwd = tk.Entry(window, textvariable=var_usr_pwd, show='*')
    entry_usr_pwd.place(x=160, y=190)
    
    def usr_login():
        pass
    def usr_sign_up():
        pass
    
    # login and sign up button
    btn_login = tk.Button(window, text='Login', command=usr_login)
    btn_login.place(x=170, y=230)
    btn_sign_up = tk.Button(window, text='Sign up', command=usr_sign_up)
    btn_sign_up.place(x=270, y=230)
    
    window.mainloop()

    3.2 例子1 登录窗口

     本节添加了Login的功能,代码如下:

    def usr_login():
        usr_name = var_usr_name.get()
        usr_pwd = var_usr_pwd.get()
        try:
            with open('usrs_info.pickle', 'rb') as usr_file:
                usrs_info = pickle.load(usr_file)
        except FileNotFoundError:
            with open('usrs_info.pickle', 'wb') as usr_file:
                usrs_info = {'admin': 'admin'}
                pickle.dump(usrs_info, usr_file)
        if usr_name in usrs_info:
            if usr_pwd == usrs_info[usr_name]:
                tk.messagebox.showinfo(title='Welcome', message='How are you? ' + usr_name)
            else:
                tk.messagebox.showerror(message='Error, your password is wrong, try again.')
        else:
            is_sign_up = tk.messagebox.askyesno('Welcome',
                                   'You have not sign up yet. Sign up today?')
            if is_sign_up:
                usr_sign_up()

     

    首先以读二进制的方式打开并下载存储用户信息的文件,如果文件不存在,则建立该文件,并且加入了用户名为admin、密码为admin的用户。

    如果用户名在用户信息文件中存在,密码输入正确时,会弹出欢迎窗口,否则则显示密码错误。

    如果用户不存在,则弹出窗口询问是否要进行注册,并通过返回的True或是False的值进行注册操作。

    运行结果如下所示:
    输入密码错误时:

    正确输入密码时:

    用户不存在时:

    3.3 例子1 登录窗口

     注册时将会弹出新窗口,如下所示:

    首先定义一个新窗口

    window_sign_up=tk.Toplevel(window)
    window_sign_up.geometry('350x200')
    window_sign_up.title('Sign up window')

    定义User name、Password和Confirm password,以及三个Entry和一个Button

    new_name = tk.StringVar()
    new_name.set('example@python.com')
    tk.Label(window_sign_up, text='User name: ').place(x=10, y= 10)
    entry_new_name = tk.Entry(window_sign_up, textvariable=new_name)
    entry_new_name.place(x=150, y=10)
    
    new_pwd = tk.StringVar()
    tk.Label(window_sign_up, text='Password: ').place(x=10, y=50)
    entry_usr_pwd = tk.Entry(window_sign_up, textvariable=new_pwd, show='*')
    entry_usr_pwd.place(x=150, y=50)
    
    new_pwd_confirm = tk.StringVar()
    tk.Label(window_sign_up, text='Confirm password: ').place(x=10, y= 90)
    entry_usr_pwd_confirm = tk.Entry(window_sign_up, textvariable=new_pwd_confirm, show='*')
    entry_usr_pwd_confirm.place(x=150, y=90)
    
    btn_confirm_sign_up = tk.Button(window_sign_up, text='Sign up', command=sign_to_Mofan_Python)
    btn_confirm_sign_up.place(x=150, y=130)

     

    接着定义函数sign_to_Mofan_Python

     def sign_to_Mofan_Python():
            np = new_pwd.get()
            npf = new_pwd_confirm.get()
            nn = new_name.get()
            with open('usrs_info.pickle', 'rb') as usr_file:
                exist_usr_info = pickle.load(usr_file)
            if np != npf:
                tk.messagebox.showerror('Error', 'Password and confirm password must be the same!')
            elif nn in exist_usr_info:
                tk.messagebox.showerror('Error', 'The user has already signed up!')
            else:
                exist_usr_info[nn] = np
                with open('usrs_info.pickle', 'wb') as usr_file:
                    pickle.dump(exist_usr_info, usr_file)
                tk.messagebox.showinfo('Welcome', 'You have successfully signed up!')
                window_sign_up.destroy()

     

    打开读取文件usrs_info,首先判断密码是否相等,如果不相等,则弹出窗口提示密码输入不一致

    如果用户名存在,则弹出窗口提示用户名已经注册

    注册合格的话,则将信息存放,pickle里面存放的是一个字典,exist_usr_info[nn] = np该句即为username:password,通过dump将新的注册信息传入到用户信息文件中。并弹出窗口提示注册成功

    最后通过destory关闭注册窗口

    完整代码如下:

    def usr_sign_up():
        def sign_to_Mofan_Python():
            np = new_pwd.get()
            npf = new_pwd_confirm.get()
            nn = new_name.get()
            with open('usrs_info.pickle', 'rb') as usr_file:
                exist_usr_info = pickle.load(usr_file)
            if np != npf:
                tk.messagebox.showerror('Error', 'Password and confirm password must be the same!')
            elif nn in exist_usr_info:
                tk.messagebox.showerror('Error', 'The user has already signed up!')
            else:
                exist_usr_info[nn] = np
                with open('usrs_info.pickle', 'wb') as usr_file:
                    pickle.dump(exist_usr_info, usr_file)
                tk.messagebox.showinfo('Welcome', 'You have successfully signed up!')
                window_sign_up.destroy()
                
        window_sign_up=tk.Toplevel(window)
        window_sign_up.geometry('350x200')
        window_sign_up.title('Sign up window')
    
        new_name = tk.StringVar()
        new_name.set('example@python.com')
        tk.Label(window_sign_up, text='User name: ').place(x=10, y=10)
        entry_new_name = tk.Entry(window_sign_up, textvariable=new_name)
        entry_new_name.place(x=150, y=10)
    
        new_pwd = tk.StringVar()
        tk.Label(window_sign_up, text='Password: ').place(x=10, y=50)
        entry_usr_pwd = tk.Entry(window_sign_up, textvariable=new_pwd, show='*')
        entry_usr_pwd.place(x=150, y=50)
    
        new_pwd_confirm = tk.StringVar()
        tk.Label(window_sign_up, text='Confirm password: ').place(x=10, y= 90)
        entry_usr_pwd_confirm = tk.Entry(window_sign_up, textvariable=new_pwd_confirm, show='*')
        entry_usr_pwd_confirm.place(x=150, y=90)
    
        btn_confirm_sign_up = tk.Button(window_sign_up, text='Sign up', command=sign_to_Mofan_Python)
        btn_confirm_sign_up.place(x=150, y=130)

     运行结果如下所示:

    当用户名已存在时:

    当密码输入不一致时:

     当注册成功时:

    点击确定后注册窗口关闭

    用注册的用户进行登录,弹出窗口:

     

     

     

     

  • 相关阅读:
    MongoDB 释放磁盘空间 db.runCommand({repairDatabase: 1 })
    RK 调试笔记
    RK Android7.1 拨号
    RK Android7.1 移植gt9271 TP偏移
    RK Android7.1 定制化 itvbox 盒子Launcher
    RK Android7.1 双屏显示旋转方向
    RK Android7.1 设置 内存条作假
    RK Android7.1 设置 蓝牙 已断开连接
    RK Android7.1 进入Camera2 亮度会增加
    RK 3128 调触摸屏 TP GT9XX
  • 原文地址:https://www.cnblogs.com/wwf828/p/7418181.html
Copyright © 2011-2022 走看看