noborder品牌羽绒服(eno是什么牌子)

【前言】这篇笔记是对PySimpleGUI模块组件的补充介绍,在这里把剩余的几个不常用的组件进行一下简单介绍,包括Tree树、ButtonMenu图形按钮菜单、ProgressBar进度条等,而重点介绍的是Table表格组件,因为数据库内容显示主要用它来完成。

noborder品牌羽绒服(eno是什么牌子)

一、PySimpleGUI模块组件补充介绍

1、表格Table组件详细属性介绍

在图形界面设计中,Table组件用来配合数据库进行内容展示是最为方便有效的,界面美观,因此有必要单独介绍,这里用实际代码来对Table的所有属性进行详细介绍,如下:

import PySimpleGUI as sg# 定义表头header = ['商品名称', '商品单价', '商品数量', '合计金额']# 定义每列是否显示,列表项目数与表头及数据相同col_map = [True, True, True, True]# 定义每列宽度,列表项目数与表头及数据相同col_widths = [12, 12, 12, 12]# 定义右键菜单right_menu = ['右键菜单', ['修改', '删除']]# 定义表格数据data = [['白菜', '3.8', '2.5', '9.5'], ['土豆', '2.2', '3', '6.6'], ['茄子', '4.2', '2.5', '10.5'], ['豆角', '6.8', '5', '34']]# 定义布局layout = [ [sg.T('购买商品明细:')], [sg.Table(values=data, # 需要显示的数据,二维列表格式 headings=header, # 表头,列表格式,与数据中的每项相对应 visible_column_map=col_map, # 每列是否显示映射,列表格式,与数据和表头中的每项相对应 def_col_width=10, # 每列的宽度 col_widths=col_widths, # 所有列的宽度总体设定,列表格式。设置这个属性后,会忽视上面的列宽设定属性 auto_size_columns=False, # 列宽自适应,通常设为假。上面两项列宽设定有数值,这项如设为真,会报错 max_col_width=50, # 最大列宽 select_mode='extended', # 表中选择行的方式,有三种:'none'不能选择行,'browse'可以单选,'extended'可以多选 display_row_numbers=True, # 是否显示行号 num_rows=6, # 显示几行 row_height=24, # 行高 justification='center', # 对齐方式:left,center,right font=('宋体', 11), # 字体和字号设定 text_color='black', # 文字颜色,黑色 background_color='silver', # 表格背景颜色,银白 alternating_row_color='gray', # 隔行颜色,灰色 selected_row_colors=('red', 'blue'), # 被选择行的文字和背景颜色 row_colors=[(1, 'red'), (3, 'white', 'green')], # 特殊指定某行颜色 header_font=('微软雅黑', 11), # 表头字体和字号 header_background_color='green', # 表头背景颜色 header_border_width=1, # 表头边线宽度 header_text_color='white', # 表头文字颜色 header_relief='raised', # 表头浮雕效果:raised,sunken,flat,ridge,groove,solid vertical_scroll_only=True, # 只有纵向滚动条 hide_vertical_scroll=False, # 是否隐藏纵向滚动条 sbar_width=20, # 滚动条的宽度 sbar_background_color=None, # 滚动条背景色 sbar_arrow_color='red', # 滚动条箭头及鼠标移动到滚动条上时的颜色 sbar_relief='grove', # 滚动条浮雕效果 sbar_arrow_width=15, # 滚动条上下箭头大小 border_width=3, # 表格外边框宽度 enable_events=False, # 是否允许产生事件 change_submits=False, # 状态改变是否提交,与产生事件属性配合使用 enable_click_events=True, # 是否允许单击某个表格项目产生事件 right_click_menu=right_menu, # 右键菜单 right_click_selects=True, # 是否允许右键选择 bind_return_key=True, # 绑定回车键 pad=((4, 4), (4, 4)), # 与其它组件的位置 p=((4, 4), (4, 4)), # 自身偏移(我自己感觉的) expand_x=True, # 自动在x轴方向展开 expand_y=True, # 自动在y轴方向展开 tooltip='表格内容', # 提示信息 key='-TABLE-' # key值 )]]window = sg.Window('批量创建按钮', layout, keep_on_top=True)while True: event, values = window.read() print(event, values)print(window['-TABLE-'].get()) # 获取table的所有内容,返回值是二维列表 if event is None: breakwindow.close()

运行效果:

视频加载中...

2、树Tree介绍

Tree树的显示效果与Table表格很相近,表元素中的许多属性适用于树元素,特别是标题信息、列宽等。但与表格不同的是,树没有标准格式。因此必须构造传递给树元素的数据结构,需要使用 TreeData 类完成的。基本过程如下:

获取 TreeData 对象将数据“插入”到树中将填充的 TreeData 对象传递给 Tree组件

演示代码如下:

import PySimpleGUI as sg# 创建树形结构数据对象treedata = sg.TreeData()# 向树形对象里插入数据(跟磁盘文件夹道理相同,根目录下有几个子目录,每个子目录还有子目录)# 创建一个节点,第一个参数代表父键值,为空('')就表示这个新建的节点就是父节点,该节点自身的键值为_F1_,接着是该节点的名称和数据treedata.insert('', '_F1_', '张三', ['2021.7', '2022.2', '2022.9'])# 创建一个子节点,它的父节点是_F1_,自身节点键值是_F1-1_,然后是该节点的名称和数据treedata.insert('_F1_', '_F1-1_', '张三妻子', ['2021.7', '2022.2', '2022.9'])treedata.insert('_F1_', '_F1-2_', '张三长子', ['2021.7', '2022.2', '2022.9'])treedata.insert('_F1_', '_F1-3_', '张三次子', ['2021.7', '2022.2', '2022.9'])# 创建第二组treedata.insert('', '_F2_', '李四', ['2021.7', '2022.2', '2022.9'])treedata.insert('_F2_', '_F2-1_', '李四妻子', ['2021.7', '2022.2', '2022.9'])treedata.insert('_F2_', '_F2-2_', '李四儿子', ['2021.7', '2022.2', '2022.9'])treedata.insert('_F2_', '_F2-3_', '李四女儿', ['2021.7', '2022.2', '2022.9'])# 创建第三组treedata.insert('', '_F3_', '王五', ['2021.7', '2022.2', '2022.9'])treedata.insert('_F3_', '_F3-1_', '王五妻子', ['2021.7', '2022.2', '2022.9'])treedata.insert('_F3_', '_F3-2_', '王五儿子', ['2021.7', '2022.2', '2022.9'])layout = [ [sg.Text('一单元每户疫苗接种情况:')], [sg.Tree(treedata, col0_heading='姓名', headings=['第一次', '第二次', '第三次'], enable_events=True)]]window = sg.Window('Tree演示', layout)while True: event, values = window.read() print(event, values) if event is None: breakwindow.close()

运行效果:

noborder品牌羽绒服(eno是什么牌子)

3、按钮菜单ButtonMenu介绍

点击按钮出现菜单的组件,支持按钮图片。代码如下:

import PySimpleGUI as sg# 定义按钮菜单项目menu_def = ['播放', ['我和我的祖国', '军中绿花', '站台']]layout = [ [sg.ButtonMenu('播放', image_filename='start.png', menu_def=menu_def, text_color='red')]]window = sg.Window('按钮菜单', layout, size=(400, 200))while True: event, values = window.read() print(event, values) if event is None: breakwindow.close()

运行效果:

视频加载中...

4、进度条ProgressBar介绍

在程序中用来提示进度的组件,这里简单用一个循环来演示一下用法,代码如下:

import PySimpleGUI as sgimport timelayout = [[sg.ProgressBar(key='-PBAR-', orientation='h', max_value=100, size=(40, 20))]]window = sg.Window('test', layout)flag = Truewhile True: event, values = window.read(timeout=10) if flag: for i in range(100): window['-PBAR-'].UpdateBar(i + 1) time.sleep(0.01) flag = not flag if event is None: breakwindow.close()

运行效果:

视频加载中...

二、综合案例介绍

1、项目介绍

本案例是利用PySimpleGUI和SQLite3模块,制作一个图形界面的员工档案管理系统,可以实现登录窗口密码验证、数据录入、删除、查询统计、更改密码、更换主题和批量导入数据等功能。

程序框架如下:

import sqlite3import PySimpleGUI as sg# 设置主题# 登录界面函数def login(): # 读取数据表中存储的用户名和密码 # 验证输入的用户名和密码与设定的值是否相同 # 验证通过后关闭登录窗口,打开主程序窗口,否则一直循环。 pass# 主窗口函数def main(): # 创建程序主界面布局layout # 第一行显示菜单栏 # 第二行显示功能按钮区,使用frame作为容器 # 第三行显示功能实现区,每一项功能都用一个frame整合,激活功能区frame的可视为真,其余为假 layout = [[欢迎页面Frame,可视默认为真],[新增页面Frame], [查询页面Frame], [删除页面Frame]] window = sg.Window('员工档案管理系统', layout) while True: event, values = window.read() if event == '新增': # 新增页面Frame可视为真,其余为假 pass if event == '查询': # 查询页面Frame可视为真,其余为假 pass if event == '删除': # 删除页面Frame可视为真,其余为假 pass if event == '返回': # 欢迎页面Frame可视为真,其余为假 pass # 添加信息、查询信息和删除信息提交事件 if event is None: break window.close()# 主程序体if __name__ == '__main__': login() # 调用登录函数 main() # 调用主窗口函数

2、数据库描述

数据库文件:DB_Company.db档案信息表:t_employee字段:eno:序号,INTEGER,primary key,autoincrementename:姓名,VARCHAR,not nullgender:性别,VARCHARbirth:出生年月,VARCHARnation:民族,VARCHARplace:籍贯,VARCHARparty:党派,VARCHARedu:学历,VARCHARpro:职称,VARCHARcard:身份证号码,VARCHARphone:电话号码,VARCHARunit:所在部门,VARCHARhonor:获得的荣誉,VARCHARpunish:所受的处罚,VARCHAR用户名密码保存表:t_user字段:uid:用户名,VARCHARpwd:密码,VARCHAR

3、创建数据库和表

import sqlite3# 创建连接,数据库名为DB_Company.db,文件不存在会自动创建conn = sqlite3.connect('DB_Company.db')# 创建游标对象cur = conn.cursor()# 编写创建表的SQL语句,表名为t_employeesql = 'CREATE TABLE IF NOT EXISTS t_employee(' \ 'eno INTEGER PRIMARY KEY AUTOINCREMENT,' \ 'ename VARCHAR NOT NULL,' \ 'gender VARCHAR,' \ 'birth VARCHAR,' \ 'nation VARCHAR,' \ 'place VARCHAR,' \ 'party VARCHAR,' \ 'edu VARCHAR,' \ 'pro VARCHAR,' \ 'card VARCHAR,' \ 'phone VARCHAR,' \ 'unit VARCHAR,' \ 'honor VARCHAR,' \ 'punish VARCHAR' \ ');'# 程序主体try: cur.execute(sql) # 执行SQL语句 print('创建表成功!')except Exception as err: print(err) print('创建表失败!')finally: cur.close() # 关闭游标 conn.close() # 关闭连接

创建完第一个表后,在Pycharm界面左侧双击数据库文件,在弹出来的终端窗口中直接使用SQL语句创建用户名密码表t_user,并添加原始账号和密码(账号:admin,密码:1111)。

4、登录窗口

# 登录界面def login():# 连接数据库,从表t_user里读取登录账号和密码 result = [] # 函数的内部变量必须先声明 login_conn = sqlite3.connect('DB_Company.db') login_cur = login_conn.cursor() sql = 'SELECT * FROM t_user' try: login_cur.execute(sql) result = login_cur.fetchall() # 获取账号和密码 except: sg.popup('发生错误,请联系管理员!') finally: login_cur.close() login_conn.close() login_layout = [ [sg.T('账号:'), sg.In(key='-USERNAME-', size=(30, 1))], [sg.T('密码:'), sg.In(key='-PASSWORD-', size=(30, 1), password_char='*')], [sg.B('登 录', key='-LOGIN-', font=('宋体', 12), size=(32, 1), bind_return_key=True)] ] login_window = sg.Window('登录窗口', login_layout, element_padding=((0, 0), (8, 8))) while True: event, values = login_window.read() # 点击登录按钮后,验证输入的用户名和密码与表中保存的是否一致,如果一致则退出循环,开始运行下面程序体,否则一直循环。 if event == '-LOGIN-': if values['-USERNAME-'] == result[0][0] and values['-PASSWORD-'] == result[0][1]: break # 点击窗口关闭按钮则直接退出程序 if event is None: exit(0) login_window.close()

运行效果:

视频加载中...

5、修改密码

修改密码的窗体是使用带有文本输入框的弹窗实现的,弹出两次窗口,第一次是输入新密码,第二次是确认输入。

# 修改密码方法def ch_password(): # 调用带有文本输入框的弹窗返回输入值 new1 = sg.popup_get_text('请输入新密码:', title='修改密码', password_char='*') # 如果点击了弹窗的关闭按钮和Cancel,返回的值都为None;如果未输入任何字符直接点OK,返回的值是空'' # 因此设定如果返回值是二者其一,则返回 if new1 in (None, ''): return new2 = sg.popup_get_text('请再次输入新密码:', title='修改密码', password_char='*') if new2 in (None, ''): return # 如果两次返回值相同,则修改t_user的pwd值为弹窗返回值 if new1 == new2: conn = sqlite3.connect('DB_Company.db') cur = conn.cursor() sql = 'UPDATE t_user SET pwd=? WHERE uid=?' cur.execute(sql, (new1, 'admin')) conn.commit() cur.close() conn.close() return sg.popup('密码修改成功!\n您下次登录将使用新密码!', title='') else: return sg.popup('两次输入的密码不相同!\n修改密码失败!', title='')

运行效果:

视频加载中...

6、更换主题

事先创建一个主题配置文件theme.ini,文件里保存默认的主题方案名称,程序开始执行就从文件里读取主题方案名称并设置主题。

# 从主题配置文件中读入设定的主题with open('theme.ini', 'r') as r_file: theme = r_file.readline() sg.theme(theme)

在菜单里点击更换主题时,通过自定义函数将所选主题对应的主题方案名称写到主题配置文件中,需要再次运行程序时才能更换主题。

# 定义设置主题函数def set_theme(t_name): with open('theme.ini', 'w') as w_file: w_file.write(t_name) return sg.popup('主题设置成功,重新打开窗口时生效!')# 点击更换主题事件if event == '深青色':set_theme('DarkTeal9')if event == '绿色':set_theme('Green ')if event == '浅棕色':set_theme('LightBrown1')if event == '绿棕褐色':set_theme('GreenTan')

运行效果:

视频加载中...

7、主窗口整体布局

主窗口布局分为三行:第一行是菜单栏,第二行是按钮栏,第三行是功能区。

(1)菜单栏

# 菜单项定义menu_def = [['设置', ['修改密码', '---', '更换主题', ['深青色', '绿色', '浅棕色', '绿棕褐色']]], ['导入', '批量导入数据'], ['帮助', '关于']]

(2)按钮栏

利用自定义函数,返回统一样式的按钮对象,便于后期对按钮大小、字体和间距等进行调整。利用列表推导式,批量创建按钮,按钮的名称保存在一个字典变量里。在本程序中,按钮对应的功能实现区并不是放在单独的窗体里,而是采取了框架frame来完成。每个功能实现区都含在一个框架Frame里,通过更改这几个功能区的Frame的可视属性,来显示相应功能区的框架Frame。而这个按钮字典变量的value值就是每个按钮对应的功能区Frame的key!功能按钮统一放在一个框架Frame里,便于调整按钮栏的样式。

# 自定义格式按钮函数def cbtn(text): return sg.B(text, pad=(0, 0), size=(5, 3), font=('宋体', 16))# 定义按钮字典变量,key值是按钮名称,value值是按钮功能区的frame的key button_dict = {'新增': '-ADD-', '查询': '-SEARCH-', '删除': '-DELETE-', '返回': '-WELCOME-'}# 定义按钮栏框架布局 button_frame = [[cbtn(i[0]) for i in button_dict.items()]]

实际效果:

noborder品牌羽绒服(eno是什么牌子)

(3)功能区

功能区是采用框架Frame实现的,进入主窗口后默认显示的是欢迎页面Frame,点击按钮栏的返回按钮也是显示这个Frame,要显示哪个Frame就把哪个Frame的可视置为真,其它的设为假。

所有Frame的布局设置如下:

欢迎页面Frame布局

# 定义欢迎页面框架布局,点击按钮区的返回按钮显示这个框架布局 welcome_frame = [[sg.Text('欢迎使用档案管理系统!', font=('宋体', 30), pad=(160, 180))]]

运行效果:

noborder品牌羽绒服(eno是什么牌子)

新增页面Frame布局

# 定义新增页面列布局add_item = ['姓名', '性别', '出生年月', '民族', '籍贯', '党派', '学历', '职称', '身份证号码', '电话号码', '所在部门']add_col1 = [[text_def(i), input_def()] for i in add_item]add_col2 = [ [sg.T('获得的荣誉:', font=('宋体', 11))], [sg.ML(size=(50, 8), font=('宋体', 10), no_scrollbar=True, pad=((0, 0), (0, 40)))], [sg.T('何时受过何种处罚:', font=('宋体', 11))], [sg.ML(size=(50, 8), font=('宋体', 10), no_scrollbar=True, pad=((0, 0), (0, 30)))], [sg.B('添加信息', key='-ADD_TEXT-', size=(20, 2), font=('宋体', 11), pad=((80, 0), (0, 20)))], [sg.B('取消操作', key='-CANCEL-', size=(20, 2), font=('宋体', 11), pad=((80, 0), (0, 0)))]]# 定义新增页面框架布局add_frame = [ [sg.Column(layout=add_col1, pad=((8, 8), (22, 0))), sg.VerticalSeparator(color='gray', pad=((20, 20), (0, 0))), sg.Column(layout=add_col2, pad=((8, 8), (22, 0)))]]

运行效果:

noborder品牌羽绒服(eno是什么牌子)

查询页面Frame布局

# 定义查询页面框架布局combo_list = ['姓名', '职称', '电话号码', '所在部门']header = ['序号'] + add_itemcol_widths = [6, 12, 5, 12, 8, 12, 12, 12, 12, 20, 16, 24]search_frame = [ [sg.T('请选择查询项并输入查询关键字:')], [sg.Combo(values=combo_list, default_value=combo_list[0], readonly=True, size=(10, 1), pad=(10, 0)), sg.In(size=(30, 1)), sg.B('查找')], [sg.Table(values=[], # 需要显示的数据,二维列表格式 headings=header, # 表头,列表格式,与数据中的每项相对应 col_widths=col_widths, # 所有列的宽度总体设定,列表格式。设置这个属性后,会忽视上面的列宽设定属性 auto_size_columns=False, select_mode='browse', # 表中选择行的方式,有三种:'none'不能选择行,'browse'可以单选,'extended'可以多选 display_row_numbers=False, # 是否显示行号 num_rows=13, # 显示几行 row_height=24, # 行高 justification='center', # 对齐方式:left,center,right font=('宋体', 10), # 字体和字号设定 header_font=('微软雅黑', 10), # 表头字体和字号 header_border_width=1, # 表头边线宽度 header_relief='raised', # 表头浮雕效果:raised,sunken,flat,ridge,groove,solid vertical_scroll_only=False, # 只有纵向滚动条 hide_vertical_scroll=False, # 是否隐藏纵向滚动条 border_width=3, # 表格外边框宽度 key='-S_TABLE-' # key值 )], [sg.B('导出到Excel文件', font=('宋体', 11), size=(15, 2), pad=((200, 50), (10, 0))), sg.B('取消操作', font=('宋体', 11), size=(15, 2), pad=((0, 0), (10, 0)))]]

运行效果:

noborder品牌羽绒服(eno是什么牌子)

删除页面Frame布局

# 定义删除页面框架布局del_header = ['序号', '姓名', '性别', '身份证号码', '电话号码', '所在部门']del_col_widths = [8, 16, 8, 24, 20, 30]del_frame = [[sg.T('请输入要删除的人员姓名:', font=('宋体', 11), pad=(10, 20)), sg.In(font=('宋体', 11), size=(20, 1)), sg.B('查找', font=('宋体', 11))], [sg.Table(values=[], # 需要显示的数据,二维列表格式 headings=del_header, # 表头,列表格式,与数据中的每项相对应 col_widths=del_col_widths, # 所有列的宽度总体设定,列表格式。设置这个属性后,会忽视上面的列宽设定属性 auto_size_columns=False, select_mode='browse', # 表中选择行的方式,有三种:'none'不能选择行,'browse'可以单选,'extended'可以多选 display_row_numbers=False, # 是否显示行号 num_rows=10, # 显示几行 row_height=24, # 行高 justification='center', # 对齐方式:left,center,right font=('宋体', 10), # 字体和字号设定 header_font=('微软雅黑', 10), # 表头字体和字号 header_border_width=1, # 表头边线宽度 header_relief='raised', # 表头浮雕效果:raised,sunken,flat,ridge,groove,solid vertical_scroll_only=True, # 只有纵向滚动条 hide_vertical_scroll=False, # 是否隐藏纵向滚动条 border_width=3, # 表格外边框宽度 key='-D_TABLE-' # key值 )], [sg.T('请输入需要删除信息的序号:', font=('宋体', 11), pad=(10, 20)), sg.In(size=(10, 1))], [sg.B('删除信息', font=('宋体', 11), size=(20, 2), pad=((180, 10), (20, 0))), sg.B('取消操作', font=('宋体', 11), size=(20, 2), pad=((30, 10), (20, 0)))]]

运行效果:

noborder品牌羽绒服(eno是什么牌子)

(4)主窗口整体布局

# 定义窗口布局layout = [ # 菜单栏 [sg.Menu(menu_def, key='-MENU-')], # 按钮栏 [sg.Frame(title='', layout=button_frame, size=(780, 67), relief='raised')], # 功能区 [sg.Frame(title='', layout=welcome_frame, key='-WELCOME-', visible=True, title_location='n', size=(780, 600), element_justification='center'), sg.Frame(title='新增档案信息', layout=add_frame, key='-ADD-', visible=False, title_location='n', size=(780, 600)), sg.Frame(title='档案信息查询', layout=search_frame, key='-SEARCH-', visible=False, title_location='n', size=(780, 600)), sg.Frame(title='删除档案信息', layout=del_frame, key='-DELETE-', visible=False, title_location='n', size=(780, 600))]]main_window = sg.Window('员工档案管理系统', layout, size=(800, 600))

(5)功能区切换

程序运行后,点击功能按钮就会调用对应的函数,而每个功能函数首先都会调用切换显示窗口(切换Frame)函数,将点击按钮对应的功能区Frame的可视置为真,其它置为假。

# 切换显示窗口方法,通过传进来的按钮名,在定义按钮字典变量里获取按钮对应的功能区frame的key值def display(button_name): for item in button_dict.items(): if item[0] == button_name: main_window[item[1]].update(visible=True) else: main_window[item[1]].update(visible=False) return

8、新增功能

# 新增界面的添加信息按钮事件if event == '-ADD_TEXT-': # 新增界面提交按钮事件 txt_list = [] if values['-ADD_IN_0-'] == '': # 姓名对应的输入框不能为空 sg.popup('姓名不能为空,请重新输入!') else: for i in range(13): txt_list.append(values[f'-ADD_IN_{i}-']) # 循环将所有输入框内容追加到列表中 try: sql = f"INSERT INTO t_employee values (NULL,'{txt_list[0]}'," \ f"'{txt_list[1]}','{txt_list[2]}','{txt_list[3]}','{txt_list[4]}'," \ f"'{txt_list[5]}','{txt_list[6]}','{txt_list[7]}','{txt_list[8]}'," \ f"'{txt_list[9]}','{txt_list[10]}','{txt_list[11]}','{txt_list[12]}')" cur.execute(sql) # 执行SQL语句,将录入的数据插入到数据表中 conn.commit() # 向数据库提交 except: sg.popup('发生未知错误,请关闭程序重新进入!') conn.rollback() # 如果发生错误则回滚

运行效果:

noborder品牌羽绒服(eno是什么牌子)

9、查询功能

查询功能分为查看全部信息、按照姓名查找、按照职称查找等,需要执行SQL查询语句的地方比较多,并且在删除功能里也需要使用,因此定义了一个专门执行SQL查询语句的函数。该函数有两个参数,一个是SQL语句字符串,另一个是Table的key值,将查询结果直接显示到指定key值的Table上。如果查询到了数据,则返回真,否则返回假,返回值用作其它按钮验证是否有数据时使用。

查询界面下方有导出Excel文档按钮,可以将查询到的数据导出到程序所在文件夹下的document子文件夹中,用来查看和打印等用途。

# 执行SQL查询语句,如果查到了信息,则更新表格显示,返回真;否则,返回假 def sql_search(sql_text, table_key): cur.execute(sql_text) s_result = cur.fetchall() if len(s_result) > 0: main_window[table_key].update(values=s_result) return True else: return False# 信息查询界面查找按钮事件if event == '-S_FIND-': if values['-COMBO-'] == '全部': # 显示所有员工信息 sql = 'SELECT * FROM t_employee' flag_search = sql_search(sql, '-S_TABLE-') # 调用自定义函数,执行传入的SQL语句,并把结果显示到指定的表格上(传入表格table的key) else: # 创建需要查询项目对应的字段名字典 s_dict = {'姓名': 'ename', '职称': 'pro', '电话号码': 'phone', '所在部门': 'unit'} txt = values['-S_INPUT-'] # 输入的内容 combo = values['-COMBO-'] # 获得下拉菜单里选择的项目 field = s_dict[combo] # 根据下拉菜单选择项目,得到对应的字段名 sql = f"SELECT * FROM t_employee WHERE {field} ='{txt}'" # 编写SQL语句 flag_search = sql_search(sql, '-S_TABLE-') # 调用自定义函数执行SQL语句,并将结果更新到给定的key的Table中 if not flag_search: sg.popup('没有查到相关信息!')# 导出Excel文档if event == '-S_EXPORT-' and flag_search: r_txt = sg.popup_get_text('请输入文件名(不加扩展名):') if not r_txt in (None, ''): file = 'document' + '\\' + r_txt + '.xlsx' if os.path.exists(file): sg.popup('该文件已经存在,请重新命名!') else: try: app = xw.App(visible=False, add_book=False) # 创建App对象(打开Excel软件),对象不可见,不自动添加工作簿 app.display_alerts = False # 关闭提示信息 app.screen_updating = False # 关闭屏幕更新,节省资源 wb = app.books.add() # 创建一个工作簿,自动生成三个工作表:Sheet1、Sheet2、Sheet3 sht = wb.sheets('Sheet1') sht.range('A2').value = ['编号'] + add_item + ['获得的荣誉', '受到的处分'] i = 2 for item in main_window['-S_TABLE-'].Values: sht.cells[i, 0].value = item i += 1 wb.save(file) # 保存工作簿,文件名为test.xlsx wb.close() # 关闭工作簿 app.kill() # 退出App对象 sg.popup('导出成功!') except: sg.popup('发生未知错误,请重新尝试!')

运行效果:

视频加载中...

10、删除功能

删除功能首先要根据姓名查找记录,然后在下面输入框里输入查找到的记录的序号(序号是唯一的,姓名可能有重名),点击删除按钮即可完成删除功能。删除成功后,再次调用查找函数,将新的查找结果更新到Table上。

# 删除界面的查找按钮事件if event == '-DEL_FIND-' and values['-DEL_INPUT-'] != '': txt = values['-DEL_INPUT-'] sql = f"SELECT eno,ename,gender,card,phone,unit FROM t_employee WHERE ename='{txt}'" flag_del = sql_search(sql, '-DEL_TABLE-') # 如果查到了要删除的信息,则该标志为真,# 删除界面的确认删除按钮事件if event == '-DEL_DELETE-' and values['-DEL_IN_NUM-'] and flag_del: r = sg.popup_ok_cancel(f"确认要删除【{values['-DEL_INPUT-']}】的信息吗?") if r == 'OK': txt = values['-DEL_IN_NUM-'] sql = f"delete from t_employee where eno={txt}" cur.execute(sql) conn.commit() sg.popup('删除成功!') txt = values['-DEL_INPUT-'] sql = f"SELECT eno,ename,gender,card,phone,unit FROM t_employee WHERE ename='{txt}'" sql_search(sql, '-DEL_TABLE-') else: continue

运行效果:

视频加载中...

11、完整代码

import osimport sqlite3import PySimpleGUI as sgimport xlwings as xw# 从主题配置文件中读入设定的主题with open('theme.ini', 'r') as r_file: theme = r_file.readline() sg.theme(theme)# 连接数据库conn = sqlite3.connect('DB_Company.db')# 创建游标cur = conn.cursor()# 登录界面def login(): # 定义列表变量,用于保存从账户表中读出来的用户名和密码列表 result = [] sql = 'SELECT * FROM t_user' try: cur.execute(sql) result = cur.fetchall() except: sg.popup('发生错误,请联系管理员!') login_layout = [ [sg.T('账号:'), sg.In(key='-USERNAME-', size=(30, 1))], [sg.T('密码:'), sg.In(key='-PASSWORD-', size=(30, 1), password_char='*')], [sg.B('登 录', key='-LOGIN-', font=('宋体', 12), size=(32, 1), bind_return_key=True)] ] login_window = sg.Window('登录窗口', login_layout, element_padding=((0, 0), (8, 8))) while True: event, values = login_window.read() # 点击登录按钮后,验证输入的用户名和密码与表中保存的是否一致,如果一致则退出循环,开始运行下面程序体,否则一直循环。 if event == '-LOGIN-': if values['-USERNAME-'] == result[0][0] and values['-PASSWORD-'] == result[0][1]: break else: sg.popup('密码有误,请重新输入!', title='') # 点击窗口关闭按钮则直接退出程序 if event is None: exit(0) login_window.close()# 主界面def main(): # 切换显示窗口方法,通过传进来的按钮名,在定义按钮字典变量里获取按钮对应的功能区frame的key值 def display(button_name): for item in button_dict.items(): if item[0] == button_name: main_window[item[1]].update(visible=True) elif item[0] != '文档': main_window[item[1]].update(visible=False) return # 修改密码方法 def ch_password(): # 调用带有文本输入框的弹窗返回输入值 new1 = sg.popup_get_text('请输入新密码:', title='修改密码', password_char='*') # 如果点击了弹窗的关闭按钮和Cancel,返回的值都为None;如果未输入任何字符直接点OK,返回的值是空'' # 因此设定如果返回值是二者其一,则返回 if new1 in (None, ''): return new2 = sg.popup_get_text('请再次输入新密码:', title='修改密码', password_char='*') if new2 in (None, ''): return # 如果两次返回值相同,则修改t_user的pwd值为弹窗返回值 if new1 == new2: sql = 'UPDATE t_user SET pwd=? WHERE uid=?' cur.execute(sql, (new1, 'admin')) conn.commit() cur.close() conn.close() return sg.popup('密码修改成功!\n您下次登录将使用新密码!', title='') else: return sg.popup('两次输入的密码不相同!\n修改密码失败!', title='') # 定义设置主题函数 def set_theme(t_name): with open('theme.ini', 'w') as w_file: w_file.write(t_name) return sg.popup('主题设置成功,重新打开窗口时生效!') # 执行SQL查询语句,如果查到了信息,则更新表格显示,返回真;否则,返回假 def sql_search(sql_text, table_key): cur.execute(sql_text) s_result = cur.fetchall() if len(s_result) > 0: main_window[table_key].update(values=s_result) return True else: return False # 自定义格式按钮函数 def cbtn(text): return sg.B(text, pad=(0, 0), size=(7, 3), font=('宋体', 16)) # 自定义新增页面文本框返回函数 def text_def(text): return sg.T(text, pad=((4, 0), (0, 22)), size=(10, 1), font=('宋体', 11)) # 自定义新增页面文本输入框返回函数 def input_def(num): return sg.In(key=f'-ADD_IN_{num}-', pad=((0, 0), (0, 22)), size=(30, 1), font=('宋体', 11), do_not_clear=False) # 菜单项定义 menu_def = [['设置', ['修改密码', '---', '更换主题', ['深青色', '绿色', '浅棕色', '绿棕褐色']]], ['导入', '批量导入数据'], ['帮助', '关于']] # 定义按钮字典变量,key值是按钮名称,value值是按钮功能区的frame的key button_dict = {'新增': '-ADD-', '查询': '-SEARCH-', '删除': '-DELETE-', '文档':'-DOCUMENT-','返回': '-WELCOME-'} # 定义按钮框架布局 button_frame = [[cbtn(i[0]) for i in button_dict.items()]] # 定义欢迎页面框架布局,点击按钮区的返回按钮显示这个框架布局 welcome_frame = [[sg.Text('欢迎使用档案管理系统!', font=('宋体', 30), pad=(160, 180))]] # 定义新增页面框架布局 # 定义新增页面列布局 add_item = ['姓名', '性别', '出生年月', '民族', '籍贯', '党派', '学历', '职称', '身份证号码', '电话号码', '所在部门'] add_col1 = [[text_def(i), input_def(add_item.index(i))] for i in add_item] add_col2 = [ [sg.T('获得的荣誉:', font=('宋体', 11))], [sg.ML(key='-ADD_IN_11-', size=(50, 8), font=('宋体', 10), no_scrollbar=True, do_not_clear=False, pad=((0, 0), (0, 40)))], [sg.T('何时受过何种处罚:', font=('宋体', 11))], [sg.ML(key='-ADD_IN_12-', size=(50, 8), font=('宋体', 10), no_scrollbar=True, do_not_clear=False, pad=((0, 0), (0, 30)))], [sg.B('添加信息', key='-ADD_TEXT-', size=(20, 2), font=('宋体', 11), pad=((80, 0), (10, 0)))]] add_frame = [ [sg.Column(layout=add_col1, pad=((8, 8), (22, 0))), sg.VerticalSeparator(color='gray', pad=((20, 20), (0, 0))), sg.Column(layout=add_col2, pad=((8, 8), (22, 0)))]] # 定义查询页面框架布局 combo_list = ['全部', '姓名', '职称', '电话号码', '所在部门'] header = ['序号'] + add_item col_widths = [6, 12, 5, 12, 8, 12, 12, 12, 12, 20, 16, 24] search_frame = [ [sg.T('请选择查询项并输入查询关键字:')], [sg.Combo(values=combo_list, default_value=combo_list[0], key='-COMBO-', readonly=True, size=(10, 1), pad=(10, 0)), sg.In(key='-S_INPUT-', size=(30, 1)), sg.B('查找', key='-S_FIND-')], [sg.Table(values=[], # 需要显示的数据,二维列表格式 headings=header, # 表头,列表格式,与数据中的每项相对应 col_widths=col_widths, # 所有列的宽度总体设定,列表格式。设置这个属性后,会忽视上面的列宽设定属性 auto_size_columns=False, select_mode='browse', # 表中选择行的方式,有三种:'none'不能选择行,'browse'可以单选,'extended'可以多选 display_row_numbers=False, # 是否显示行号 num_rows=13, # 显示几行 row_height=24, # 行高 alternating_row_color='silver', justification='center', # 对齐方式:left,center,right font=('宋体', 10), # 字体和字号设定 header_font=('微软雅黑', 10), # 表头字体和字号 header_border_width=1, # 表头边线宽度 header_relief='raised', # 表头浮雕效果:raised,sunken,flat,ridge,groove,solid vertical_scroll_only=False, # 只有纵向滚动条 hide_vertical_scroll=False, # 是否隐藏纵向滚动条 border_width=3, # 表格外边框宽度 key='-S_TABLE-' # key值 )], [sg.B('导出到Excel文件', key='-S_EXPORT-', font=('宋体', 11), size=(18, 2), pad=((300, 0), (15, 0)))]] # 定义删除页面框架布局 del_header = ['序号', '姓名', '性别', '身份证号码', '电话号码', '所在部门'] del_col_widths = [8, 16, 8, 24, 20, 30] del_frame = [[sg.T('请输入要删除信息的人员姓名:', font=('宋体', 11), pad=(10, 20)), sg.In(key='-DEL_INPUT-', font=('宋体', 11), size=(20, 1)), sg.B('查找', key='-DEL_FIND-', font=('宋体', 11))], [sg.Table(values=[], # 需要显示的数据,二维列表格式 headings=del_header, # 表头,列表格式,与数据中的每项相对应 col_widths=del_col_widths, # 所有列的宽度总体设定,列表格式。设置这个属性后,会忽视上面的列宽设定属性 auto_size_columns=False, select_mode='browse', # 表中选择行的方式,有三种:'none'不能选择行,'browse'可以单选,'extended'可以多选 display_row_numbers=False, # 是否显示行号 alternating_row_color='silver', num_rows=10, # 显示几行 row_height=24, # 行高 justification='center', # 对齐方式:left,center,right font=('宋体', 10), # 字体和字号设定 header_font=('微软雅黑', 10), # 表头字体和字号 header_border_width=1, # 表头边线宽度 header_relief='raised', # 表头浮雕效果:raised,sunken,flat,ridge,groove,solid vertical_scroll_only=True, # 只有纵向滚动条 hide_vertical_scroll=False, # 是否隐藏纵向滚动条 border_width=3, # 表格外边框宽度 key='-DEL_TABLE-' # key值 )], [sg.T('请输入需要删除信息的序号:', font=('宋体', 11), pad=(10, 20)), sg.In(key='-DEL_IN_NUM-', size=(10, 1))], [sg.B('删除信息', key='-DEL_DELETE-', font=('宋体', 11), size=(20, 2), pad=((300, 10), (20, 0)))]] # 定义窗口布局 layout = [ [sg.Menu(menu_def, key='-MENU-')], [sg.Frame(title='', layout=button_frame, size=(780, 67), relief='raised')], [sg.Frame(title='', layout=welcome_frame, key='-WELCOME-', visible=True, title_location='n', size=(780, 600), element_justification='center'), sg.Frame(title='新增档案信息', layout=add_frame, key='-ADD-', visible=False, title_location='n', size=(780, 600)), sg.Frame(title='档案信息查询', layout=search_frame, key='-SEARCH-', visible=False, title_location='n', size=(780, 600)), sg.Frame(title='删除档案信息', layout=del_frame, key='-DELETE-', visible=False, title_location='n', size=(780, 600))] ] main_window = sg.Window('员工档案管理系统', layout, size=(800, 600)) flag_search = False # 查询页面用来标志是否检测到信息 flag_del = False # 删除页面里用来标志是否检测到要删除的人员姓名 while True: event, values = main_window.read() print(event, values) if event == '修改密码': ch_password() if event == '深青色': set_theme('DarkTeal9') if event == '绿色': set_theme('Green ') if event == '浅棕色': set_theme('LightBrown1') if event == '绿棕褐色': set_theme('GreenTan') # 点击功能按钮,切换显示窗口 if event == '新增': display('新增') if event == '查询': display('查询') if event == '删除': display('删除') if event=='文档': path=os.getcwd() directory = path+'\\'+'document' os.system("explorer.exe %s" % directory) if event == '返回': display('返回') # 新增界面的添加信息按钮事件 if event == '-ADD_TEXT-': txt_list = [] if values['-ADD_IN_0-'] == '': sg.popup('姓名不能为空,请重新输入!') else: for i in range(13): txt_list.append(values[f'-ADD_IN_{i}-']) try: sql = f"INSERT INTO t_employee values (NULL,'{txt_list[0]}'," \ f"'{txt_list[1]}','{txt_list[2]}','{txt_list[3]}','{txt_list[4]}'," \ f"'{txt_list[5]}','{txt_list[6]}','{txt_list[7]}','{txt_list[8]}'," \ f"'{txt_list[9]}','{txt_list[10]}','{txt_list[11]}','{txt_list[12]}')" cur.execute(sql) conn.commit() except: sg.popup('发生未知错误,请关闭程序重新进入!') conn.rollback() # 信息查询界面查找按钮事件 if event == '-S_FIND-': if values['-COMBO-'] == '全部': # 显示所有员工信息 sql = 'SELECT * FROM t_employee' flag_search = sql_search(sql, '-S_TABLE-') # 调用自定义函数,执行传入的SQL语句,并把结果显示到指定的表格上(传入表格table的key) else: # 创建需要查询项目对应的字段名字典 s_dict = {'姓名': 'ename', '职称': 'pro', '电话号码': 'phone', '所在部门': 'unit'} txt = values['-S_INPUT-'] # 输入的内容 combo = values['-COMBO-'] # 获得下拉菜单里选择的项目 field = s_dict[combo] # 根据下拉菜单选择项目,得到对应的字段名 sql = f"SELECT * FROM t_employee WHERE {field} ='{txt}'" # 编写SQL语句 flag_search = sql_search(sql, '-S_TABLE-') # 调用自定义函数执行SQL语句,并将结果更新到给定的key的Table中 if not flag_search: sg.popup('没有查到相关信息!') if event == '-S_EXPORT-' and flag_search: r_txt = sg.popup_get_text('请输入文件名(不加扩展名):') if not r_txt in (None, ''): file = 'document' + '\\' + r_txt + '.xlsx' if os.path.exists(file): sg.popup('该文件已经存在,请重新命名!') else: try: app = xw.App(visible=False, add_book=False) # 创建App对象(打开Excel软件),对象不可见,不自动添加工作簿 app.display_alerts = False # 关闭提示信息 app.screen_updating = False # 关闭屏幕更新,节省资源 wb = app.books.add() # 创建一个工作簿,自动生成三个工作表:Sheet1、Sheet2、Sheet3 sht = wb.sheets('Sheet1') sht.range('A2').value = ['编号'] + add_item + ['获得的荣誉', '受到的处分'] i = 2 for item in main_window['-S_TABLE-'].Values: sht.cells[i, 0].value = item i += 1 wb.save(file) # 保存工作簿,文件名为test.xlsx wb.close() # 关闭工作簿 app.kill() # 退出App对象 sg.popup('导出成功!') except: sg.popup('发生未知错误,请重新尝试!') # 删除界面的查找按钮事件 if event == '-DEL_FIND-' and values['-DEL_INPUT-'] != '': txt = values['-DEL_INPUT-'] sql = f"SELECT eno,ename,gender,card,phone,unit FROM t_employee WHERE ename='{txt}'" flag_del = sql_search(sql, '-DEL_TABLE-') # 如果查到了要删除的信息,则该标志为真, # 删除界面的确认删除按钮事件 if event == '-DEL_DELETE-' and values['-DEL_IN_NUM-'] and flag_del: r = sg.popup_ok_cancel(f"确认要删除【{values['-DEL_INPUT-']}】的信息吗?") if r == 'OK': txt = values['-DEL_IN_NUM-'] sql = f"delete from t_employee where eno={txt}" cur.execute(sql) conn.commit() sg.popup('删除成功!') txt = values['-DEL_INPUT-'] sql = f"SELECT eno,ename,gender,card,phone,unit FROM t_employee WHERE ename='{txt}'" sql_search(sql, '-DEL_TABLE-') else: continue if event is None: cur.close() conn.close() break main_window.close()if __name__ == '__main__': login() # 调用登录函数 main() # 调用主函数

本文内容源自网友投稿,多成号仅提供信息存储服务不拥有所有权。如有侵权,请联系站长删除。qq97伍4伍0叁11