下图是在网上搜寻的一个案例图样,经过了调整修改,登录时界面图如下:
登录后点击百货店铺按钮,界面如下
一、创建root窗口:
geometry接收一个字符串,也就是需要建立的窗口尺寸和位置,geometry('宽x高+x坐标+y坐标'),宽和高中间是英文字母x,不是中文的乘号。root.resizable(False, False)是固定窗口大小,最后需要调用root.mainloop(),保持窗口一直存在。
import tkinterroot = tkinter.Tk()
root.title('销售数据录入平台')
root.geometry('1000x660+460+100')
root.resizable(False, False)def main():root.mainloop()if __name__ == '__main__':main()
将整个root分成三个部分,一是最上面的黑色背景的顶部菜单栏控件,二是中间带图片的辅助信息控件,三是菜单栏点击后链接的下面主体控件。
二、建立顶部菜单栏控件:
顶部先用一个Frame作为容器,填充黑色背景。然后是左边是平台的名字,只需要显示,不用点击产生链接,用Label方法。后面的百货店铺、超市店铺、美食广场和登录用户是可以点击的按钮,用Button方法。Lable和Button两种方法的第一个参数都是上层容器,后面是文本、字体、前景色和背景色,然后直接调用place函数准确定位。
def head():frame = tkinter.Frame(root, bg='black')frame.place(width=1000, height=60)tkinter.Label(frame, text='销售数据录入平台', font=('黑体', 20), fg='white', bg='black').place(x=20, y=15)tkinter.Button(frame, text='百货店铺', font=('黑体', 12), fg='white', bg='black', command=body_store,relief='flat', activeforeground='grey', overrelief='raised').place(x=330, y=20)tkinter.Button(frame, text='超市店铺', font=('黑体', 12), fg='white', bg='black', command=body_supermarket,relief='flat', activeforeground='grey', overrelief='raised').place(x=490, y=20)tkinter.Button(frame, text='美食广场', font=('黑体', 12), fg='white', bg='black', command=body_food,relief='flat', activeforeground='grey', overrelief='raised').place(x=650, y=20)tkinter.Button(frame, text='用户登录', font=('黑体', 12), fg='white', bg='black', command=login,relief='flat', activeforeground='grey', overrelief='raised').place(x=810, y=20)def body_store():print('百货店铺')passdef body_supermarket():print('超市店铺')passdef body_food():print('美食广场')passdef login():print('登录用户')pass
这样就完成了菜单栏的控件布局,在main函数中增加head(),然后执行程序:
relief='flat', activeforeground='grey', overrelief='raised'三个参数分别实现效果:第一个是控制正常显示效果,第二个是按下鼠标左键时的效果,第三个是鼠标悬浮在按钮上的效果。
点击后可以看到控制台正确打印出信息:百货店铺 。
三、辅助信息控件
基本都差不多,只是增加了一个个图片的处理。
仍然是先给这部分一个单独Frame容器,填充颜色。然后是文字部分用Lable控件,其它用Button控件完成。
tkinter在处理图片的时候,如果包装到函数里面,图片就丢失了,变成了一个白块。
def information():frame = tkinter.Frame(root, bg=color)frame.place(width=940, height=140, x=30, y=100)img = tkinter.PhotoImage(file='bg1.png')tkinter.Label(frame, image=img).place(width=230, height=120, x=10, y=10)
执行结果:
网上有介绍说是执行完后图片被释放了,修改方法是再增加一条代码:tkinter.Label.image = img
def information():frame = tkinter.Frame(root, bg=color)frame.place(width=940, height=140, x=30, y=100)img = tkinter.PhotoImage(file='bg1.png')tkinter.Label(frame, image=img).place(width=230, height=120, x=10, y=10)tkinter.Label.image = img
这样确实也能实现,但是看着怪怪的的,而且在后面写登录函数再次使用这个图片时候,图片又神奇的消失了:
我想能不能在函数外部定义image呢?居然成立了。image = tkinter.PhotoImage(file='bg1.png')必须写在root = tkinter.Tk()的后面,如果写在 tkinter.Tk()前面会报错。
import tkinterroot = tkinter.Tk()
root.title('销售数据录入平台')
root.geometry('1000x660+460+100')
root.resizable(False, False)color = '#48D1CC'
image = tkinter.PhotoImage(file='bg1.png')def information():frame = tkinter.Frame(root, bg=color)frame.place(width=940, height=140, x=30, y=100)tkinter.Label(frame, image=image).place(width=230, height=120, x=10, y=10)
这种写法至少现在的情况可以完美的解决tkinter在显示图片丢失的问题。而且再次使用该图片时可以直接赋值使用,没有发生再丢失现象。完整的辅助信息栏代码:
def information():frame = tkinter.Frame(root, bg=color)frame.place(width=940, height=140, x=30, y=100)tkinter.Label(frame, image=image).place(width=230, height=120, x=10, y=10)tkinter.Label(frame, text='平台使用教程', font=('黑体', 25), fg='black', bg=color).place(x=265, y=25)tkinter.Button(frame, text='操作文档', font=('黑体', 12), fg='blue', bg=color, command=lambda: print('操作文档'),relief='flat', activeforeground='grey', overrelief='raised').place(x=520, y=37)tkinter.Button(frame, text='教学视频', font=('黑体', 12), fg='blue', bg=color, command=lambda: print('教学视频'),relief='flat', activeforeground='grey', overrelief='raised').place(x=620, y=37)tkinter.Button(frame, text='常见问题', font=('黑体', 12), fg='blue', bg=color, command=lambda: print('常见问题'),relief='flat', activeforeground='grey', overrelief='raised').place(x=720, y=37)text = '用户注册分自行注册和管理员后台注册,自行注册需确保管理员后台中注册权限已开启,\n\n点击新用户注册,填写注册信息进行注册,新入职人员需管理员后台开启权限。'tkinter.Label(frame, text=text, font=('黑体', 10), fg='black', bg=color, justify='left').place(x=265, y=83)
四、现在来写登录界面:
登录界面需要分两部分,一个是已有用户验证密码登录,一个是新注册用户录入用户名及新密码。在弹出登录界面时,通过root.attributes('-disabled', 1)锁定根窗口,还需要调用prodocol函数,login_toplevel.protocol('WM_DELETE_WINDOW', root.quit)和根窗口建立协议,没有正常登录关闭登录窗口时关闭根窗口,否则根窗口将无法关闭了。
def login():print('登录用户')login_toplevel = tkinter.Toplevel(root)login_toplevel.title('用户登录')login_toplevel.geometry('250x200+835+400')login_toplevel.attributes('-topmost', 1)login_toplevel.resizable(False, False)login_toplevel.grab_set()login_toplevel.protocol('WM_DELETE_WINDOW', root.quit)tkinter.Label(login_toplevel, image=image).place(width=250, height=100, x=0, y=0)tkinter.Label(login_toplevel, text='用户', font=('黑体', 12)).place(width=50, height=25, x=20, y=105)tkinter.Label(login_toplevel, text='密码', font=('黑体', 12)).place(width=50, height=25, x=20, y=135)(user := tkinter.Entry(login_toplevel)).place(width=150, height=25, x=70, y=105)(password := tkinter.Entry(login_toplevel)).place(width=150, height=25, x=70, y=135)tkinter.Button(login_toplevel, text='登录', command=lambda: login_in()).place(width=100, height=30, x=20, y=165)tkinter.Button(login_toplevel, text='注册', command=lambda: register_in()).place(width=100, height=30, x=130, y=165)def login_in():print('登录')passdef register_in():print('注册')pass
这里用的海象赋值法:(:=),还挺有意思!
五、完善登录、注册方法
def login_in():print('登录')if not (user.get() and password.get()):tkinter.messagebox.showerror('登录信息', '用户名或密码不能为空!', parent=login_toplevel)elif user.get() + ',' + password.get() in read_data():tkinter.messagebox.showinfo('登录信息', '登录成功', parent=login_toplevel)login_toplevel.destroy()root.attributes('-disable', 0)root.attributes('-topmost', 1)else:tkinter.messagebox.showwarning('登录信息', '用户名或密码错误!', parent=login_toplevel)def register_in():print('注册')register_toplevel = tkinter.Toplevel(root)register_toplevel.title('注册信息')register_toplevel.geometry('250x130+835+400')register_toplevel.resizable(False, False)register_toplevel.attributes('-topmost', 1)login_toplevel.attributes('-disabled', 1)register_toplevel.protocol('WM_DELETE_WINDOW', login_toplevel.quit)tkinter.Label(register_toplevel, text='新用户', font=('黑体', 12)).place(width=50, height=25, x=20, y=5)tkinter.Label(register_toplevel, text='新密码', font=('黑体', 12)).place(width=50, height=25, x=20, y=35)tkinter.Label(register_toplevel, text='新密码', font=('黑体', 12)).place(width=50, height=25, x=20, y=65)(new_user := tkinter.Entry(register_toplevel)).place(width=150, height=25, x=75, y=5)(password1 := tkinter.Entry(register_toplevel)).place(width=150, height=25, x=75, y=35)(password2 := tkinter.Entry(register_toplevel)).place(width=150, height=25, x=75, y=65)tkinter.Button(register_toplevel, text='注册', command=lambda: register_new()).place(width=100, height=30, x=20, y=95)tkinter.Button(register_toplevel, text='取消', command=lambda: register_toplevel.quit()).place(width=100, height=30, x=130, y=95)def register_new():if not (new_user.get() and password1.get()):tkinter.messagebox.showerror('注册提示', '用户名或密码不能为空!', parent=register_toplevel)elif password1.get() != password2.get():tkinter.messagebox.showerror('注册提示', '两次密码不一致!', parent=register_toplevel)else:tkinter.messagebox.showinfo('注册提示', '注册成功!', parent=register_toplevel)with open('data.csv', 'a') as file:file.write(f'{new_user.get()},{password1.get()}\n')register_toplevel.destroy()login_toplevel.attributes('-disable', 0)def read_data():with open('data.csv', 'r') as file:return map(str.strip, file.readlines())
六、补充一些百货店铺信息:
白色的线条是用Label标签完成
def body_store():print('百货店铺')frame = tkinter.Frame(root, bg=color)frame.place(width=940, height=380, x=30, y=260)tkinter.Label(frame, bg='white').place(width=170, height=5, x=0, y=205)tkinter.Label(frame, bg='white').place(width=765, height=5, x=175, y=40)tkinter.Label(frame, bg='white').place(width=5, height=380, x=170, y=0)tkinter.Label(frame, text='销售数据', font=('黑体', 12), fg='black', bg=color).place(x=10, y=10)tkinter.Button(frame, text='批发客户管理', font=('黑体', 10), bg=color, fg='black', command=lambda: print('批发客户管理'),relief='flat', activebackground='grey', overrelief='raised').place(x=40, y=50)tkinter.Button(frame, text='销售批发管理', font=('黑体', 10), bg=color, fg='black', command=lambda: print('销售批发管理'),relief='flat', activebackground='grey', overrelief='raised').place(x=40, y=80)tkinter.Button(frame, text='批发价格管理', font=('黑体', 10), bg=color, fg='black', command=lambda: print('批发价格管理'),relief='flat', activebackground='grey', overrelief='raised').place(x=40, y=110)tkinter.Button(frame, text='批发结算管理', font=('黑体', 10), bg=color, fg='black', command=lambda: print('批发结算管理'),relief='flat', activebackground='grey', overrelief='raised').place(x=40, y=140)tkinter.Button(frame, text='批发人员管理', font=('黑体', 10), bg=color, fg='black', command=lambda: print('批发人员管理'),relief='flat', activebackground='grey', overrelief='raised').place(x=40, y=170)tkinter.Label(frame, text='数据中心', font=('黑体', 12), fg='black', bg=color).place(x=10, y=220)tkinter.Button(frame, text='销售数据查询', font=('黑体', 10), bg=color, fg='black', command=lambda: print('销售数据查询'),relief='flat', activebackground='grey', overrelief='raised').place(x=40, y=260)tkinter.Button(frame, text='库存数据查询', font=('黑体', 10), bg=color, fg='black', command=lambda: print('库存数据查询'),relief='flat', activebackground='grey', overrelief='raised').place(x=40, y=290)
七、完整代码:
import tkinter
import tkinter.messageboxroot = tkinter.Tk()
root.title('销售数据录入平台')
root.geometry('1000x660+460+100')
root.resizable(False, False)color = '#48D1CC'
image = tkinter.PhotoImage(file='bg1.png')def information():frame = tkinter.Frame(root, bg=color)frame.place(width=940, height=140, x=30, y=100)tkinter.Label(frame, image=image).place(width=230, height=120, x=10, y=10)tkinter.Label(frame, text='平台使用教程', font=('黑体', 25), fg='black', bg=color).place(x=265, y=25)tkinter.Button(frame, text='操作文档', font=('黑体', 12), fg='blue', bg=color, command=lambda: print('操作文档'),relief='flat', activeforeground='grey', overrelief='raised').place(x=520, y=37)tkinter.Button(frame, text='教学视频', font=('黑体', 12), fg='blue', bg=color, command=lambda: print('教学视频'),relief='flat', activeforeground='grey', overrelief='raised').place(x=620, y=37)tkinter.Button(frame, text='常见问题', font=('黑体', 12), fg='blue', bg=color, command=lambda: print('常见问题'),relief='flat', activeforeground='grey', overrelief='raised').place(x=720, y=37)text = '用户注册分自行注册和管理员后台注册,自行注册需确保管理员后台中注册权限已开启,\n\n点击新用户注册,填写注册信息进行注册,新入职人员需管理员后台开启权限。'tkinter.Label(frame, text=text, font=('黑体', 10), fg='black', bg=color, justify='left').place(x=265, y=83)def head():frame = tkinter.Frame(root, bg='black')frame.place(width=1000, height=60)tkinter.Label(frame, text='销售数据录入平台', font=('黑体', 20), fg='white', bg='black').place(x=20, y=15)tkinter.Button(frame, text='百货店铺', font=('黑体', 12), fg='white', bg='black', command=body_store,relief='flat', activeforeground='grey', overrelief='raised').place(x=330, y=20)tkinter.Button(frame, text='超市店铺', font=('黑体', 12), fg='white', bg='black', command=body_supermarket,relief='flat', activeforeground='grey', overrelief='raised').place(x=490, y=20)tkinter.Button(frame, text='美食广场', font=('黑体', 12), fg='white', bg='black', command=body_food,relief='flat', activeforeground='grey', overrelief='raised').place(x=650, y=20)tkinter.Button(frame, text='用户登录', font=('黑体', 12), fg='white', bg='black', command=login,relief='flat', activeforeground='grey', overrelief='raised').place(x=810, y=20)def body_store():print('百货店铺')frame = tkinter.Frame(root, bg=color)frame.place(width=940, height=380, x=30, y=260)tkinter.Label(frame, bg='white').place(width=170, height=5, x=0, y=205)tkinter.Label(frame, bg='white').place(width=765, height=5, x=175, y=40)tkinter.Label(frame, bg='white').place(width=5, height=380, x=170, y=0)tkinter.Label(frame, text='销售数据', font=('黑体', 12), fg='black', bg=color).place(x=10, y=10)tkinter.Button(frame, text='批发客户管理', font=('黑体', 10), bg=color, fg='black', command=lambda: print('批发客户管理'),relief='flat', activebackground='grey', overrelief='raised').place(x=40, y=50)tkinter.Button(frame, text='销售批发管理', font=('黑体', 10), bg=color, fg='black', command=lambda: print('销售批发管理'),relief='flat', activebackground='grey', overrelief='raised').place(x=40, y=80)tkinter.Button(frame, text='批发价格管理', font=('黑体', 10), bg=color, fg='black', command=lambda: print('批发价格管理'),relief='flat', activebackground='grey', overrelief='raised').place(x=40, y=110)tkinter.Button(frame, text='批发结算管理', font=('黑体', 10), bg=color, fg='black', command=lambda: print('批发结算管理'),relief='flat', activebackground='grey', overrelief='raised').place(x=40, y=140)tkinter.Button(frame, text='批发人员管理', font=('黑体', 10), bg=color, fg='black', command=lambda: print('批发人员管理'),relief='flat', activebackground='grey', overrelief='raised').place(x=40, y=170)tkinter.Label(frame, text='数据中心', font=('黑体', 12), fg='black', bg=color).place(x=10, y=220)tkinter.Button(frame, text='销售数据查询', font=('黑体', 10), bg=color, fg='black', command=lambda: print('销售数据查询'),relief='flat', activebackground='grey', overrelief='raised').place(x=40, y=260)tkinter.Button(frame, text='库存数据查询', font=('黑体', 10), bg=color, fg='black', command=lambda: print('库存数据查询'),relief='flat', activebackground='grey', overrelief='raised').place(x=40, y=290)def body_supermarket():print('超市店铺')frame = tkinter.Frame(root, bg=color)frame.place(width=940, height=380, x=30, y=260)tkinter.Label(frame, bg='white').place(width=170, height=5, x=0, y=205)tkinter.Label(frame, bg='white').place(width=765, height=5, x=175, y=40)tkinter.Label(frame, bg='white').place(width=5, height=380, x=170, y=0)def body_food():print('美食广场')frame = tkinter.Frame(root, bg=color)frame.place(width=940, height=380, x=30, y=260)tkinter.Label(frame, bg='white').place(width=170, height=5, x=0, y=205)tkinter.Label(frame, bg='white').place(width=765, height=5, x=175, y=40)tkinter.Label(frame, bg='white').place(width=5, height=380, x=170, y=0)def login():print('登录用户')login_toplevel = tkinter.Toplevel(root)login_toplevel.title('用户登录')login_toplevel.geometry('250x200+835+400')login_toplevel.attributes('-topmost', 1)login_toplevel.resizable(False, False)login_toplevel.grab_set()login_toplevel.protocol('WM_DELETE_WINDOW', root.quit)tkinter.Label(login_toplevel, image=image).place(width=250, height=100, x=0, y=0)tkinter.Label(login_toplevel, text='用户', font=('黑体', 12)).place(width=50, height=25, x=20, y=105)tkinter.Label(login_toplevel, text='密码', font=('黑体', 12)).place(width=50, height=25, x=20, y=135)(user := tkinter.Entry(login_toplevel)).place(width=150, height=25, x=70, y=105)(password := tkinter.Entry(login_toplevel)).place(width=150, height=25, x=70, y=135)tkinter.Button(login_toplevel, text='登录', command=lambda: login_in()).place(width=100, height=30, x=20, y=165)tkinter.Button(login_toplevel, text='注册', command=lambda: register_in()).place(width=100, height=30, x=130, y=165)def login_in():print('登录')if not (user.get() and password.get()):tkinter.messagebox.showerror('登录信息', '用户名或密码不能为空!', parent=login_toplevel)elif user.get() + ',' + password.get() in read_data():tkinter.messagebox.showinfo('登录信息', '登录成功', parent=login_toplevel)login_toplevel.destroy()root.attributes('-disable', 0)root.attributes('-topmost', 1)else:tkinter.messagebox.showwarning('登录信息', '用户名或密码错误!', parent=login_toplevel)def register_in():print('注册')register_toplevel = tkinter.Toplevel(root)register_toplevel.title('注册信息')register_toplevel.geometry('250x130+835+400')register_toplevel.resizable(False, False)register_toplevel.attributes('-topmost', 1)login_toplevel.attributes('-disabled', 1)register_toplevel.protocol('WM_DELETE_WINDOW', login_toplevel.quit)tkinter.Label(register_toplevel, text='新用户', font=('黑体', 12)).place(width=50, height=25, x=20, y=5)tkinter.Label(register_toplevel, text='新密码', font=('黑体', 12)).place(width=50, height=25, x=20, y=35)tkinter.Label(register_toplevel, text='新密码', font=('黑体', 12)).place(width=50, height=25, x=20, y=65)(new_user := tkinter.Entry(register_toplevel)).place(width=150, height=25, x=75, y=5)(password1 := tkinter.Entry(register_toplevel)).place(width=150, height=25, x=75, y=35)(password2 := tkinter.Entry(register_toplevel)).place(width=150, height=25, x=75, y=65)tkinter.Button(register_toplevel, text='注册', command=lambda: register_new()).place(width=100, height=30, x=20, y=95)tkinter.Button(register_toplevel, text='取消', command=lambda: register_toplevel.quit()).place(width=100, height=30, x=130, y=95)def register_new():if not (new_user.get() and password1.get()):tkinter.messagebox.showerror('注册提示', '用户名或密码不能为空!', parent=register_toplevel)elif password1.get() != password2.get():tkinter.messagebox.showerror('注册提示', '两次密码不一致!', parent=register_toplevel)else:tkinter.messagebox.showinfo('注册提示', '注册成功!', parent=register_toplevel)with open('data.csv', 'a') as file:file.write(f'{new_user.get()},{password1.get()}\n')register_toplevel.destroy()login_toplevel.attributes('-disable', 0)def read_data():with open('data.csv', 'r') as file:return map(str.strip, file.readlines())def main():head()information()login()root.mainloop()if __name__ == '__main__':main()