范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

Python学习笔记数据库TinyDB配合多窗口界面及表格组件综合实例

  本篇学习笔记将利用轻量级数据库TinyDB存储信息,配合Qt多窗口用户界面,实现数据库新增、修改、删除和查询等功能,最终使用Qt的表格组件将信息展现出来。
  一、轻量级数据库TinyDB介绍
  Python中的TinyDB,是一个纯Python编写的轻量级的面向文档的数据库,源码一共只有1800行代码,没有外部依赖项。TinyDB的数据储存方式主要是json文件,也就是 Python 中的字典类型。对于小型项目而言,使用TinyDB数据库非常适合。它有如下特点:轻便:源代码很少,小巧轻便可随意迁移:TinyDB基于面向文档的存储,数据库只有一个json文件,不依赖任何服务,拷贝即可迁移易用性:TinyDB的API非常简单和干净,易于使用非依赖性:TinyDB既不需要外部服务器,也不需要任何来自PyPI的依赖项,支持Python3.6以上的所有版本可扩展性:在中间件的帮助下,可以轻松扩展TinyDB行为,以满足特定的需求
  (一)创建json数据库和表
  TinyDB是一个第三方包,在使用之前需要先安装,如命令行格式:pip install tinydb,或者在集成开发环境中安装。
  创建数据库和表的代码模板如下:from tinydb import TinyDB  # 导入TinyDB类  db=TinyDB("my_db.json")  # 创建名为my_db的json数据库 table=db.table("student")  # 创建名为student的表  db.close()  # 关闭数据库
  (二)插入数据
  1、插入单条数据 table.insert({"name":"张三","age":23,"class":"三年五班"}) table.insert({"name":"李四","age":"30","class":"三年一班"})
  【注】插入语句insert的返回值是所添加数据在表中的索引值,表的索引值从1开始,顺序递增。运行以下代码观察索引值变化情况:from tinydb import TinyDB  db=TinyDB("my_db.json") table=db.table("student")  index1=table.insert({"name":"张三","age":23,"class":"三年五班"}) index2=table.insert({"name":"李四","age":"30","class":"三年一班"})  print(index1,index2) db.close()  运行结果: 第一次运行的结果是1 2,第二次是3 4,依此类推……
  2、插入多条数据 from tinydb import TinyDB  db = TinyDB("my_db.json") table = db.table("student")  data = [{"name": "小明", "age": 13, "class": "三年五班"}, {"name": "小刚", "age": "12", "class": "三年一班"},         {"name": "小强", "age": "15", "class": "三年一班"}, {"name": "小红", "age": "13", "class": "三年一班"},         {"name": "小花", "age": "14", "class": "三年一班"}] index = table.insert_multiple(data)  # 插入多条数据,即数据以列表形式添加  print(index) db.close()  运行结果:[1, 2, 3, 4, 5]
  【注】在插入多条数据时,索引值是一个列表。
  (三)查询数据
  1、查询数据库中的表 num=db.tables() print(num)  运行结果: {"student", "_default"}
  【注】"_default"表是默认存在的
  2、使用all函数查询所有数据 string=table.all() print(string)  # 输出all函数查询到的所有结果  运行结果: [{"name": "小明", "age": 13, "class": "三年五班"}, {"name": "小刚", "age": "12", "class": "三年一班"}, {"name": "小强", "age": "15", "class": "三年一班"}, {"name": "小红", "age": "13", "class": "三年一班"}, {"name": "小花", "age": "14", "class": "三年一班"}, {"name": "小明", "age": 13, "class": "三年五班"}, {"name": "小刚", "age": "12", "class": "三年一班"}, {"name": "小强", "age": "15", "class": "三年一班"}, {"name": "小红", "age": "13", "class": "三年一班"}, {"name": "小花", "age": "14", "class": "三年一班"}]
  3、使用where进行条件查询 from tinydb import TinyDB, where  # 需要导入where  str1 = table.search(where("name") == "小花")  # 在表中查询名字是小花的记录 str2 = table.search(where("age") > 13) print(str1) print(str2)  运行结果: [{"name": "小花", "age": "14", "class": "三年一班"}] [{"name": "小强", "age": 15, "class": "三年一班"}, {"name": "小花", "age": 14, "class": "三年一班"}]
  4、使用Query查询
  Query是数据库查询组件,使用非常方便灵活,需要事先导入Query。演示代码如下:stuQuery = Query()  # 创建查询对象  query_data = table.search(stuQuery.cls == "三年一班")  # 查询班级是三年一班的记录 print(query_data)  query_data = table.search(stuQuery.age <= 13)  # 查询年龄小于等于13的记录 print(query_data)  query_data=table.search(stuQuery.age<=13 and stuQuery.cls=="三年五班") print(query_data)  query_data=table.search((stuQuery.age<13) | (stuQuery.age>14)) print(query_data)  运行结果: [{"name": "小刚", "age": 12, "cls": "三年一班"}, {"name": "小强", "age": 15, "cls": "三年一班"}, {"name": "小红", "age": 13, "cls": "三年一班"}, {"name": "小花", "age": 14, "cls": "三年一班"}] [{"name": "小明", "age": 13, "cls": "三年五班"}, {"name": "小刚", "age": 12, "cls": "三年一班"}, {"name": "小红", "age": 13, "cls": "三年一班"}] [{"name": "小明", "age": 13, "cls": "三年五班"}] [{"name": "小刚", "age": 12, "cls": "三年一班"}, {"name": "小强", "age": 15, "cls": "三年一班"}]
  【注】数据库中的字段名一定不能与系统的保留关键字重复,例如上面的学生数据库的班级字段,如果写成class,那么在使用Query查询时程序就会出错。
  (四)修改数据
  1、使用where方法 index = table.update({"cls": "三年二班"}, where("name") == "小刚") print("修改记录的索引是:", index) print(table.search(where("name") == "小刚"))  运行结果: 修改记录的索引是: [2] [{"name": "小刚", "age": 12, "cls": "三年二班"}]
  2、使用Query方法 index=table.update({"cls": "三年三班"}, stuQuery.name=="小强") print("修改记录的索引是:", index) print(table.search(where("name") == "小强"))  运行结果: 修改记录的索引是: [3] [{"name": "小强", "age": 15, "cls": "三年三班"}]
  (五)删除数据
  1、删除所有数据 table.truncate() print(table.all())  运行结果: []
  2、删除符合条件的数据 del_index = table.remove(stuQuery.cls == "三年一班")  # 删除班级是三年一班的数据 print("删除的索引是:", del_index) print(table.all())  运行结果: 删除的索引是: [4, 5] [{"name": "小明", "age": 13, "cls": "三年五班"}, {"name": "小刚", "age": 12, "cls": "三年二班"}, {"name": "小强", "age": 15, "cls": "三年三班"}]二、多窗口图形界面介绍
  在实际开发项目时,多窗口图形界面是经常要使用的,例如登录窗口、点击功能按钮弹出对应功能实现窗口等等。使用多窗口图形界面,必须要理清窗口的继承关系,以及设置窗口的模态属性,也就是子窗口是否阻塞主窗口。
  (一)创建多窗口的基本模型
  下面实例演示创建多窗口的基础模型。首先,在Qt设计大师中创建一个主窗口和两个子窗口,主窗口设置了背景颜色,分别保存这三个窗口文件,并将三个窗口的ui文件转换成py文件,准备静态加载。
  1、加载多窗口代码 from PySide6.QtWidgets import QApplication, QWidget from PySide6.QtGui import Qt from ui_test1 import Ui_MForm  # 导入窗口1的Ui类 from ui_test2 import Ui_SForm1  # 导入窗口2的Ui类 from ui_test3 import Ui_SForm2  # 导入窗口3的Ui类   # 自定义主窗口的类 class MainWindow(QWidget):     def __init__(self):         super(MainWindow, self).__init__()         self.ui1 = Ui_MForm()         self.ui1.setupUi(self)          # 设置两个子窗口对象值为None,代表窗口未打开         self.s_window1 = None         self.s_window2 = None          # 主窗口的按钮单击信号和槽         self.ui1.pushButton.clicked.connect(self.show_Form)      # 显示子窗口的方法     def show_Form(self):         # 如果子窗口1是未打开状态,则创建该窗口         # 没有这个检测的环节,点击打开窗口按钮会反复打开子窗口         if self.s_window1 is None:             self.s_window1 = SubWindow1()             self.s_window1.show()             self.s_window1.move(300, 200)         # 如果子窗口2是未打开状态,则创建该窗口         if self.s_window2 is None:             self.s_window2 = SubWindow2()             self.s_window2.show()             self.s_window2.move(900, 200)   # 自定义子窗口1的类,继承主窗口的类MainWindow,因此主窗口的背景颜色设置在子窗口1里生效 class SubWindow1(MainWindow):     def __init__(self):         super(SubWindow1, self).__init__()         self.ui2 = Ui_SForm1()         self.ui2.setupUi(self)   # 自定义子窗口2的类,继承通用组件QWidget,因此主窗口的背景颜色设置在子窗口2里不生效 class SubWindow2(QWidget):     def __init__(self):         super(SubWindow2, self).__init__()         self.ui3 = Ui_SForm2()         self.ui3.setupUi(self)   if __name__ == "__main__":     app = QApplication([])     window = MainWindow()     window.show()     app.exec()
  【注】子窗口1的自定义类继承了主窗口的自定义类MainWindow,子窗口2的自定义类继承通用组件QWidget,所以子窗口1的背景颜色跟主窗口一样,而子窗口2没有背景颜色。
  2、效果演示
  视频加载中...
  (二)实现子窗口跟随主窗口一起关闭
  在上面多窗口基本模型的视频演示中可以看到,主窗口和两个子窗口可以自由关闭,但是当主窗口关闭时,子窗口并不能跟随关闭。为了解决这个问题,我们要重写主类的closeEvent关闭事件方法。
  1、重写主类closeEvent方法代码 # 一定要在主窗口的自定义类里书写此代码 def closeEvent(self, event):     sys.exit(0)
  2、效果演示
  视频加载中...
  【注】程序运行后,关闭主窗口则子窗口1和子窗口2都跟着关闭;关闭子窗口1,主窗口和子窗口2也跟着关闭,因为子窗口1继承自主窗口类,关闭事件跟主窗口是相同的;关闭子窗口2不会影响主窗口和子窗口1。
  (三)设置子窗口模态属性
  在做多窗口项目开发时,有时要求子窗口不能同时打开,以免处理不好发生数据混乱的情况,例如新增数据和删除数据子窗口。为此,我们就需要用子窗口来阻塞主窗口进程,这里就需要设置子窗口的模态属性。
  1、在Qt设计大师中设置
  点击需要设置模态属性的子窗口,在窗口的QWidget属性设置中找到windowModality,将属性值改成ApplicationModal,保存窗口并将相应的ui文件转换成py文件即可。模态属性设置如下图:
  设置子窗口的模态属性
  2、在代码中设置 self.s_window2 = SubWindow2() # 子窗口模态属性设置一定要放在show()方法之前 self.s_window2.setWindowModality(Qt.ApplicationModal) self.s_window2.show()
  (四)多窗口演示完整代码 import sys from PySide6.QtWidgets import QApplication, QWidget from PySide6.QtGui import Qt from ui_test1 import Ui_MForm  # 导入窗口1的Ui类 from ui_test2 import Ui_SForm1  # 导入窗口2的Ui类 from ui_test3 import Ui_SForm2  # 导入窗口3的Ui类   # 自定义主窗口的类 class MainWindow(QWidget):     def __init__(self):         super(MainWindow, self).__init__()         self.ui1 = Ui_MForm()         self.ui1.setupUi(self)          # 设置两个子窗口对象值为None,代表窗口未打开         self.s_window1 = None         self.s_window2 = None          # 主窗口的按钮单击信号和槽         self.ui1.pushButton.clicked.connect(self.show_Form)      # 显示子窗口的方法     def show_Form(self):         # 如果子窗口1是未打开状态,则创建该窗口         if self.s_window1 is None:             self.s_window1 = SubWindow1()             self.s_window1.show()             self.s_window1.move(300, 200)         # 如果子窗口2是未打开状态,则创建该窗口         if self.s_window2 is None:             self.s_window2 = SubWindow2()             # 设置子窗口2的模态方式为阻塞主程序,或者在Qt设计大师的窗口属性里设置             # 程序运行后,只有子窗口2是活动的,主窗口不可点击,只有子窗口2关闭后才可以操作主窗口             self.s_window2.setWindowModality(Qt.ApplicationModal)             self.s_window2.show()             self.s_window2.move(900, 200)      # 重写父类的关闭事件方法,实现关闭主窗口后子窗口跟着关闭的功能     def closeEvent(self, event):         sys.exit(0)   # 自定义子窗口1的类,继承主窗口的类MainWindow,因此主窗口的背景颜色设置在子窗口1里生效 class SubWindow1(MainWindow):     def __init__(self):         super(SubWindow1, self).__init__()         self.ui2 = Ui_SForm1()         self.ui2.setupUi(self)   # 自定义子窗口2的类,继承通用组件QWidget,因此主窗口的背景颜色设置在子窗口2里不生效 class SubWindow2(QWidget):     def __init__(self):         super(SubWindow2, self).__init__()         self.ui3 = Ui_SForm2()         self.ui3.setupUi(self)   if __name__ == "__main__":     app = QApplication([])     window = MainWindow()     window.show()     app.exec()
  视频加载中...三、综合实例开发
  在介绍图形界面开发之PySimpleGUI模块时,我们使用SQLite3和PySimpleGUI模块制作了一个员工档案信息管理系统,现在我们使用PySide6和TinyDB对该系统进行重新开发,旨在加深对PySide6和TinyDB的理解,并未在安全性方面做任何处理。
  (一)准备数据库
  1、数据库描述
  本案例采用轻量级数据库TinyDB存储员工档案信息。数据库、表和字段设置如下:【数据库文件】:company.json  【档案信息表】:employee 【字段】:编号、姓名、性别、出生年月、民族、籍贯、党派、学历、职称、身份证号码 电话号码、所在部门、获得的荣誉、所受的处罚  【用户名密码保存表】:user 字段:uid、pwd
  2、初始化数据库
  首先创建一个init.py文件,使用代码创建数据库和用户名密码保存表,并插入一条默认用户名和密码数据,代码如下:from tinydb import TinyDB  db = TinyDB("company.json")  # 创建json数据库,数据库名称为company.json  table = db.table("user")  # 创建用来存储用户名和密码的表,表名为user  table.insert({"uid": "admin", "pwd": "1111"})  # 设置初始用户名和密码  db.close()
  (二)设计窗口
  窗口包括:主窗口,登录窗口,新增信息窗口,查询/删除信息窗口,修改信息窗口和修改密码窗口。
  1、主窗口
  在Qt设计大师里创建主窗口时,最好使用Main Window模版,如果不需要菜单栏、工具栏和地址栏可以手动去除。Main Window类的窗口功能比较健全,设置背景图片、布局等都不会出现问题。采用Form类创建的窗口,在代码中创建窗口类时,如果继承QMainWindow类,那么布局会混乱;如果继承QWidget类,那么背景图片就会不显示。
  我在做这个实例时,就是采用Form模版创建的主窗口,然后在代码中创建窗口类时继承QWidget类,就发生了背景图片不显示的情况,折磨了很久才找到原因。由于不想重新设计主窗口,于是将主窗口的最大尺寸和最小尺寸均设置成窗口实际尺寸,让窗口不能通过拖动改变尺寸,也就不需要布局了,最后在创建窗口类的代码中继承QMainWindow类,总算解决了背景图片不显示的问题。窗口ui文件名称:ui_main.ui窗口对象名称:MainForm,由于是多窗口应用,因此窗口对象的名称最好不采用默认的Form或者MainWindow包含组件:四个Tool Button,工具按钮的toolButtonStyle属性设置为ToolButtonTextUnderIcon,即按钮文本在图标下面。autoRaise属性设置为真,即工具按钮自动浮起,否则是凹陷状态,按钮周围有外框影响美观背景图片:在窗口对象的样式表中,使用#MainForm{}的形式设置背景图片,这是为了只给名称为MainForm的组件即窗口添加背景图片,否则窗口上的所有元素都会加载这个背景图片。样式表代码如下:#MainForm{background-image: url(:/images/icon/background.jpg);}窗口外观:如下图
  主窗口示例图片
  2、登录窗口
  设计登录窗口不要采用Dialog模版,无论点击OK还是Cancel按钮,Dialog类的窗口都会关闭,不能持久显示。窗口ui文件名称:ui_login.ui窗口对象名称:LoginForm包含组件:两个标签组件,两个单行文本输入框组件,一个按钮组件背景图片:与主窗口设置背景图片方法相同窗口外观:如下图
  登录窗口示例图片
  3、新增信息窗口 窗口ui文件名称:ui_add.ui窗口对象名称:AddForm包含组件:一个Group Box容器类组件,用来装载录入员工基本信息的所有组件,起到归类的作用。一个Tab Widget标签组件,用来放置"获得的荣誉"和"所受的处罚"两个多行文本输入框,节省空间。一个Table Widget表格组件,用来显示新录入的员工信息。剩余是标签、单行文本输入框和按钮组件,整个窗口设置了布局,支持拖放改变窗口大小。另外,在窗口的样式表中对表格组件的标题栏进行了设置,样式表代码如下:QHeaderView::section{;background-color:rgb(225,225,225);height:28px;}背景图片:无窗口外观:如下图
  新增信息窗口示例图片
  4、查询/删除信息窗口 窗口ui文件名称:ui_search_del.ui窗口对象名称:SDForm包含组件:一个Table Widget表格组件,标题栏设置与新增信息中相同。剩余是标签、单行文本输入框和按钮组件,整个窗口设置了布局,支持拖放改变窗口大小背景图片:无窗口外观:如下图
  查询/删除信息窗口示例图片
  5、修改信息窗口 窗口ui文件名称:ui_change.ui窗口对象名称:ChangeForm包含组件:与新增信息窗口基本相同背景图片:无窗口外观:如下图
  修改信息窗口示例图片
  (三)代码部分
  1、登录窗口和主窗口显示代码
  (1)思路分析创建登录窗口类创建主窗口类创建登录窗口实例对象显示登录窗口,即程序运行首先显示登录窗口判断登录是否成功,如果登录成功,则关闭登录窗口本身,然后创建主窗口实例对象并显示主窗口
  (2)实例代码from PySide6.QtWidgets import QApplication, QMainWindow, QMessageBox from tinydb import TinyDB, Query from ui_login import Ui_LoginForm  # 导入登录窗口ui文件 from ui_main import Ui_MainForm  # 导入主窗口ui文件   # 创建登录窗口类,这里必须继承QMainWindow类,如果继承QWidget,那么背景图片无法显示 class LoginWindow(QMainWindow):     def __init__(self):         super(LoginWindow, self).__init__()         self.uiLogin = Ui_LoginForm()         self.uiLogin.setupUi(self)          self.main_window = None  # 预设主窗口对象          # 密码输入框回车和登录按钮单击信号,都连接到登录方法         self.uiLogin.lineEdit_2.returnPressed.connect(self.login)         self.uiLogin.pushButton.clicked.connect(self.login)      # 登录方法     def login(self):         if self.uiLogin.lineEdit.text() == "" or self.uiLogin.lineEdit_2.text() == "":             return         db = TinyDB("company.json")         table = db.table("user")         query = Query()         username = "admin"         # 搜索结果是列表包含字典的格式,因此需要先用索引值获得字典数据,再用字典的key获取value值         password = table.search(query.uid == username)[0]["pwd"]         if self.uiLogin.lineEdit.text() == username and self.uiLogin.lineEdit_2.text() == password:             self.close()  # 如果登录成功,则登录窗口本身关闭。因为不再使用登录窗口,所以没有使用隐藏方法。             self.main_window = MainWindow()  # 创建主窗口实例对象             self.main_window.show()  # 显示主窗口         else:             QMessageBox.information(self, "提示信息", "用户名或密码错误,请重新输入!")   # 创建主窗口类,同样要继承QMainWindow类,以显示背景图片 class MainWindow(QMainWindow):     def __init__(self):         super(MainWindow, self).__init__()         self.uiMain = Ui_MainForm()         self.uiMain.setupUi(self)   if __name__ == "__main__":     app = QApplication([])     window = LoginWindow()  # 创建登录窗口实例对象     window.show()  # 显示登录窗口     app.exec()
  2、主程序完整代码
  在主程序中,除了上面介绍的登录窗口和主程序窗口显示代码外,剩下就是显示新增信息、查询/删除信息和修改信息窗口的代码。每个窗口具体功能实现部分,都在各自的py文件中,在主程序中将这些py文件以模块的形式导入,再引用模块内的窗口类就可以了。修改密码功能,在主程序中直接采用QInputDialog输入对话框完成。主程序文件名为mainProgram.py,完整代码如下:from PySide6.QtWidgets import QApplication, QMainWindow, QMessageBox, QInputDialog from PySide6.QtGui import Qt from tinydb import TinyDB, Query from ui_login import Ui_LoginForm from ui_main import Ui_MainForm from add import AddWindow  # 导入新增信息模块即py文件中的窗口类 from search_del import SDWindow  # 导入搜索/删除信息模块中的窗口类 from change import ChangeWindow  # 导入修改信息模块中的窗口类   # 创建登录窗口类,这里必须继承QMainWindow类,如果继承QWidget,那么背景图片无法显示 class LoginWindow(QMainWindow):     def __init__(self):         super(LoginWindow, self).__init__()         self.uiLogin = Ui_LoginForm()         self.uiLogin.setupUi(self)          self.main_window = None  # 预设主窗口对象          # 密码输入框回车和登录按钮单击信号,都连接到登录方法         self.uiLogin.lineEdit_2.returnPressed.connect(self.login)         self.uiLogin.pushButton.clicked.connect(self.login)      # 登录方法     def login(self):         if self.uiLogin.lineEdit.text() == "" or self.uiLogin.lineEdit_2.text() == "":             return         db = TinyDB("company.json")         table = db.table("user")         query = Query()         username = "admin"         # 搜索结果是列表包含字典的格式,因此需要先用索引值获得字典数据,再用字典的key获取value值         password = table.search(query.uid == username)[0]["pwd"]         db.close()         if self.uiLogin.lineEdit.text() == username and self.uiLogin.lineEdit_2.text() == password:             self.close()  # 如果登录成功,则登录窗口本身关闭。因为不再使用登录窗口,所以没有使用隐藏方法。             self.main_window = MainWindow()  # 创建主窗口实例对象             self.main_window.show()  # 显示主窗口         else:             QMessageBox.information(self, "提示信息", "用户名或密码错误,请重新输入!")   # 创建主窗口类,同样要继承QMainWindow类,以显示背景图片 class MainWindow(QMainWindow):     def __init__(self):         super(MainWindow, self).__init__()         self.uiMain = Ui_MainForm()         self.uiMain.setupUi(self)          self.add_window = None  # 预设新增信息窗口对象         self.search_window = None  # 预设搜索删除信息窗口对象         self.change_window = None  # 预设修改信息窗口对象          self.uiMain.toolButton_add.clicked.connect(self.show_add)  # 新增信息按钮点击信号和槽         self.uiMain.toolButton_search.clicked.connect(self.show_search)  # 查询删除信息按钮点击信号和槽         self.uiMain.toolButton_change.clicked.connect(self.show_change)  # 新增信息按钮点击信号和槽         self.uiMain.toolButton_pwd.clicked.connect(self.show_pwd)  # 修改密码按钮单击信号和槽      # 显示新增信息窗口方法     def show_add(self):         self.add_window = AddWindow()         self.add_window.setWindowModality(Qt.ApplicationModal)  # 为窗口设置模态属性         self.add_window.show()      # 显示查询/删除信息窗口方法     def show_search(self):         self.search_window = SDWindow()         self.search_window.setWindowModality(Qt.ApplicationModal)  # 为窗口设置模态属性         self.search_window.show()      # 显示修改信息窗口方法     def show_change(self):         self.change_window = ChangeWindow()         self.change_window.setWindowModality(Qt.ApplicationModal)  # 为窗口设置模态属性         self.change_window.show()      # 修改密码方法     def show_pwd(self):         pwd1, okPressed1 = QInputDialog.getText(self, "修改密码", "请输入新密码:")         if okPressed1:             pwd2, okPressed2 = QInputDialog.getText(self, "确认修改", "请再次输入新密码:")             if okPressed2:                 if pwd1 == pwd2:                     db = TinyDB("company.json")                     table = db.table("user")                     query = Query()                     table.update({"pwd": pwd1}, query.uid == "admin")                     db.close()                     QMessageBox.information(self, "修改密码", "密码修改成功!")                 else:                     QMessageBox.information(self, "修改密码", "两次输入不相同,请重新输入!")   if __name__ == "__main__":     app = QApplication([])     window = LoginWindow()  # 创建登录窗口实例对象     window.show()  # 显示登录窗口     app.exec()
  3、新增信息模块代码
  新增信息模块名为add.py,代码如下:import copy from PySide6.QtWidgets import QApplication, QWidget, QMessageBox, QTableWidgetItem from PySide6.QtGui import Qt from tinydb import TinyDB from ui_add import Ui_AddForm   # 创建新增信息窗口类 class AddWindow(QWidget):     def __init__(self):         super(AddWindow, self).__init__()         self.uiAdd = Ui_AddForm()         self.uiAdd.setupUi(self)          self.add_list = []  # 定义存储所有新增信息的列表,为的是往数据库里添加         self.add_dict = dict()  # 定义存储每行新增信息的字典          self.uiAdd.pushButton.clicked.connect(self.addList)  # 添加到新增列表按钮信号和槽         self.uiAdd.pushButton_2.clicked.connect(self.saveDB)  # 保存到数据库按钮信号和槽          self.table_init()  # 调用table表格初始化方法         self.id_init()  # 调用编号初始化方法      # 编号初始化方法,自动生成编号     def id_init(self):         db = TinyDB("company.json")         table = db.table("employee")         content = table.all()  # 读取数据表的所有内容         rows = self.uiAdd.tableWidget.rowCount()  # 获取Table的行数                  if rows == 0 and content == []:             self.uiAdd.edit_0.setText("A001")  # 如果数据表和Table中的内容都是空的,则编号设置为A001             self.uiAdd.edit_1.setFocus()  # 将焦点设置在姓名输入框             return         if rows != 0:  # 如果Table中有数据,则取得最后一行的编号             id_data = self.uiAdd.tableWidget.item(rows - 1, 0).text()         else:             id_data = content[-1]["编号"]  # 如果Table中没有数据,则取得数据表中最后一条记录的编号数据          id_new = "A%03d" % (int(id_data[1:]) + 1)  # 将原有编号后面数字加1,一共显示3位,前面用0补充         self.uiAdd.edit_0.setText(id_new)  # 将新增信息窗口的编号输入框内容设置为新编号         self.uiAdd.edit_1.setFocus()  # 将焦点设置在姓名输入框      # 表格初始化方法     def table_init(self):         # 调整各列的列宽         self.uiAdd.tableWidget.setColumnWidth(0, 50)         self.uiAdd.tableWidget.setColumnWidth(1, 60)         self.uiAdd.tableWidget.setColumnWidth(2, 40)         self.uiAdd.tableWidget.setColumnWidth(3, 60)         self.uiAdd.tableWidget.setColumnWidth(4, 40)         self.uiAdd.tableWidget.setColumnWidth(5, 60)         self.uiAdd.tableWidget.setColumnWidth(6, 60)         self.uiAdd.tableWidget.setColumnWidth(7, 60)         self.uiAdd.tableWidget.setColumnWidth(8, 80)         self.uiAdd.tableWidget.setColumnWidth(9, 150)         self.uiAdd.tableWidget.setColumnWidth(10, 90)      # 添加到新增列表按钮单击方法     def addList(self):         # 判断编号和姓名输入框内容是否为空         if self.uiAdd.edit_0.text() == "" or self.uiAdd.edit_1.text() == "":             QMessageBox.critical(self, "错误信息", "编号和姓名不能为空,请重新输入")         else:             row = self.uiAdd.tableWidget.rowCount()  # 获取表格总行数             self.uiAdd.tableWidget.setRowCount(row + 1)  # 表格当前行等于总行数加1              # 将单行文本输入框的名称设置为连续序列形式,如edit_0、edit_1……,利用eval函数循环将各个单行文本输入框内容添加到表格当前行中             for col in range(12):                 label_text = eval(f"self.uiAdd.label_{col}.text()")                 edit_text = eval(f"self.uiAdd.edit_{col}.text()")                 self.uiAdd.tableWidget.setItem(row, col, QTableWidgetItem(edit_text))                 # 设置单元格对齐方式,需要使用Qt类的AlignmentFlag属性                 self.uiAdd.tableWidget.item(row, col).setTextAlignment(Qt.AlignmentFlag.AlignCenter)                  # 构建新增信息的字典数据,下面语句还可以写成self.add_dict.update({f"{label_text}":f"{edit_text}"})                 self.add_dict[f"{label_text}"] = edit_text              # 单行文本输入框内容添加完毕后,将两个多行文本输入框的内容添加到最后两列中             edit_text = self.uiAdd.plainTextEdit_0.toPlainText()             self.uiAdd.tableWidget.setItem(row, 12, QTableWidgetItem(edit_text))             self.add_dict["获得的荣誉"] = edit_text  # 字典里也添加该信息             edit_text = self.uiAdd.plainTextEdit_1.toPlainText()             self.uiAdd.tableWidget.setItem(row, 13, QTableWidgetItem(edit_text))             self.add_dict["所受的处罚"] = edit_text             # 将一行信息的字典添加到列表中,这里必须对字典进行深拷贝,否则下次输入改变字典内容,列表内容随着更改             self.add_list.append(copy.deepcopy(self.add_dict))              # 使用跟上面相同方法,将所有输入框内容清除             for i in range(12):                 eval(f"self.uiAdd.edit_{i}.clear()")             self.uiAdd.plainTextEdit_0.clear()             self.uiAdd.plainTextEdit_1.clear()             self.id_init()  # 所有输入框内容清空后,调用编号初始化方法,自动生成编号      # 保存到数据库按钮单击方法     def saveDB(self):         choice = QMessageBox.question(self, "确认信息", "确认要将数据保存到数据库吗?")         if choice == QMessageBox.No:             return         db = TinyDB("company.json")         table = db.table("employee")         table.insert_multiple(self.add_list)         QMessageBox.information(self, "提示信息", "数据保存成功!")         print(table.all())         self.uiAdd.tableWidget.clearContents()  # 清除表格内容,但不清除标题,clear方法会连标题都清除         self.uiAdd.tableWidget.setRowCount(0)         self.add_list.clear()   if __name__ == "__main__":     app = QApplication([])     window = AddWindow()     window.show()     app.exec()
  运行效果:
  视频加载中...
  4、查询/删除信息模块代码
  新增信息模块名为search_del.py,代码如下:from PySide6.QtWidgets import QApplication, QWidget, QTableWidgetItem, QMessageBox from PySide6 import QtCore from PySide6.QtGui import Qt from ui_search_del import Ui_SDForm from tinydb import TinyDB, Query   class SDWindow(QWidget):     def __init__(self):         super(SDWindow, self).__init__()         self.uiSD = Ui_SDForm()         self.uiSD.setupUi(self)          self.table_init()  # 调用表格初始化方法          self.uiSD.button_s.clicked.connect(self.search)  # 提交搜索按钮单击信号         self.uiSD.button_d.clicked.connect(self.delete)  # 删除按钮单击信号      # 表格初始化方法     def table_init(self):         # 调整各列的列宽         self.uiSD.tableWidget.setColumnWidth(0, 50)         self.uiSD.tableWidget.setColumnWidth(1, 60)         self.uiSD.tableWidget.setColumnWidth(2, 40)         self.uiSD.tableWidget.setColumnWidth(3, 60)         self.uiSD.tableWidget.setColumnWidth(4, 40)         self.uiSD.tableWidget.setColumnWidth(5, 60)         self.uiSD.tableWidget.setColumnWidth(6, 60)         self.uiSD.tableWidget.setColumnWidth(7, 60)         self.uiSD.tableWidget.setColumnWidth(8, 80)         self.uiSD.tableWidget.setColumnWidth(9, 150)         self.uiSD.tableWidget.setColumnWidth(10, 90)      def search(self):         db = TinyDB("company.json")         table = db.table("employee")         query = Query()         self.query_data = []         # 按照所输入位置和内容搜索信息         if self.uiSD.edit_id.text():             self.query_data = table.search(query.编号 == self.uiSD.edit_id.text())         if self.uiSD.edit_name.text():             self.query_data = table.search(query.姓名 == self.uiSD.edit_name.text())         if self.uiSD.edit_card.text():             self.query_data = table.search(query.身份证号码 == self.uiSD.edit_card.text())         if self.uiSD.edit_cls.text():             self.query_data = table.search(query.所在部门 == self.uiSD.edit_cls.text())          db.close()         self.show_data(self.query_data)  # 调用显示数据方法      # 显示数据方法     def show_data(self, data):         row = 0  # 初始行为0         self.uiSD.tableWidget.setRowCount(len(data))  # 设置表格总行数为搜索到的记录数         for item in data:             col = 0  # 初始列为0             for key in item:                 self.uiSD.tableWidget.setItem(row, col, QTableWidgetItem(item[key]))                 # 设置单元格对齐方式,需要使用Qt类的AlignmentFlag属性                 self.uiSD.tableWidget.item(row, col).setTextAlignment(Qt.AlignmentFlag.AlignCenter)                 col += 1             row += 1      # 删除信息按钮单击方法     def delete(self):         selected_data = self.uiSD.tableWidget.selectedItems()  # 获取选中的所有表格项目         self.id_list = []  # 定义存储选中信息的编号列表         rows = len(selected_data) // 14  # 计算一共选中几行信息,因为获取的数据是所有单元格,每行有14个单元格          for i in range(rows):             self.id_list.append(selected_data[i * 14].text())  # 循环获取所有准备删除的编号数据,放置在列表中          choice = QMessageBox.question(self, "删除信息", f"确认要删除编号为:{self.id_list}的数据吗?")         if choice == QMessageBox.No:             return          db = TinyDB("company.json")         table = db.table("employee")         query = Query()         # 将数据库中包含要删除编号的记录全部删掉         for i in self.id_list:             table.remove(query.编号 == i)         db.close()          self.search()  # 调用查询方法,更新表格显示          QMessageBox.information(self,"删除信息","信息删除成功!")   if __name__ == "__main__":     app = QApplication([])     window = SDWindow()     window.show()     app.exec()
  运行效果:
  视频加载中...
  5、修改信息模块代码
  修改信息模块名为change.py,代码如下:from PySide6.QtWidgets import QApplication, QWidget, QMessageBox from tinydb import TinyDB, Query from ui_change import Ui_ChangeForm   # 创建修改信息窗口类 class ChangeWindow(QWidget):     def __init__(self):         super(ChangeWindow, self).__init__()         self.uiChange = Ui_ChangeForm()         self.uiChange.setupUi(self)         self.load_data = []  # 预设存储要修改信息列表变量         self.uiChange.pushButton.clicked.connect(self.load)  # 读入信息按钮信号         self.uiChange.pushButton_2.clicked.connect(self.save)  # 保存信息按钮信号      # 读入信息方法     def load(self):         if not self.uiChange.edit_0.text():             QMessageBox.information(self, "提示信息", "请输入要修改信息的编号,然后点读入信息按钮!")             return         db = TinyDB("company.json")         table = db.table("employee")         query = Query()         self.load_data = table.search(query.编号 == self.uiChange.edit_0.text())         db.close()         if len(self.load_data) == 0:             QMessageBox.information(self, "提示信息", "输入的编号不存在,请重新输入!")             return         i = 0         for item in self.load_data[0].values():             if i in (0, 12, 13):  # 跳过第0、12和13条项目                 i+=1                 continue             eval(f"self.uiChange.edit_{i}.setEnabled(True)")  # 循环设置单行文本输入框的可用状态为真             eval(f"self.uiChange.edit_{i}.setText(item)")  # 设置文本输入框的内容为读入的相应数据             i += 1          # 设置两个多行文本编辑器的状态和内容         self.uiChange.plainTextEdit_0.setEnabled(True)         self.uiChange.plainTextEdit_1.setEnabled(True)         self.uiChange.plainTextEdit_0.setPlainText(self.load_data[0]["获得的荣誉"])         self.uiChange.plainTextEdit_1.setPlainText(self.load_data[0]["所受的处罚"])      # 保存信息方法     def save(self):         db = TinyDB("company.json")         table = db.table("employee")         query = Query()         for i in range(12):  # 以相应的标签的文本为key,以对应的单行文本输入框的内容为value,更新数据库内容             key=eval(f"self.uiChange.label_{i}.text()")             value=eval(f"self.uiChange.edit_{i}.text()")             table.update({key:value},query.编号==self.uiChange.edit_0.text())          table.update({"获得的荣誉":self.uiChange.plainTextEdit_0.toPlainText()},query.编号==self.uiChange.edit_0.text())         table.update({"所受的处罚":self.uiChange.plainTextEdit_1.toPlainText()},query.编号==self.uiChange.edit_0.text())          QMessageBox.information(self,"提示信息","信息保存成功!")   if __name__ == "__main__":     app = QApplication([])     window = ChangeWindow()     window.show()     app.exec()
  运行效果:
  视频加载中...
  6、修改密码功能
  修改密码功能没有设计窗口,而是在主程序中直接采用QInputDialog输入对话框完成。代码如下:# 修改密码方法 def show_pwd(self):     pwd1, okPressed1 = QInputDialog.getText(self, "修改密码", "请输入新密码:")     if okPressed1:         pwd2, okPressed2 = QInputDialog.getText(self, "确认修改", "请再次输入新密码:")         if okPressed2:             if pwd1 == pwd2:                 db = TinyDB("company.json")                 table = db.table("user")                 query = Query()                 table.update({"pwd": pwd1}, query.uid == "admin")                 db.close()                 QMessageBox.information(self, "修改密码", "密码修改成功!")             else:                 QMessageBox.information(self, "修改密码", "两次输入不相同,请重新输入!")
  (四)整体效果演示
  视频加载中...

通信乱象该如何整治?人民日报狠批过后,通信现象会有改善吗?岂止是通信乱象,通信乱象只不过是行业乱象的冰山一角,保险银行医院等等,都一样乱象横生,从服务行业的乱象看,服务就是拣财,服务的背后就是算计,是为利是图,甚至是陷阱。通信乱象如何治理你上中学最快乐的事情是什么时候?看到此题,又一次唤起我对高中时代两位美女同学强烈的思念。怎能忘啊?不能忘。是她们和班上同学的关心和陪伴,让我度过了人生中最快乐的两年美好时光。我的一位美女同学叫田小丫。我们是一个村家有一女,复旦研究生,毕业想就职德勤咨询,大家觉得这个工作有前途吗?德勤很不错啊!做咨询也很有前途,收入也没得说,就是真的会很辛苦!讲个我好朋友的亲身经历给你听。我大学时的好朋友大学毕业去了安永做咨询,同属四大,应该薪资待遇发展方向都比较接近,我说适合便秘人的推粪机,不是火龙果,具体指的是哪种食物?正常人应该起码每天一次大便,或者至多不超过两天要有一次大便,长期形成这种规律性,是对健康比较有利的。便秘的人一般指两三天以上的时间,才有一次大便,而且多半排便的时候比较费劲,弄得自事业单位退休中人为什么设十年过渡期?事业单位退休中人为什么设十年过度期?2014年以前退休的亊业老人养老金计算,主要与退前工资有关,按照国家规定工龄在35年以上按在职工资90发放,工龄2030年按85发放。一般国家机大家觉得直播电商还会好吗?看待问题不能太片面了,李佳琦被评为新经济人物,相信大家都知道吧。这说明了什么?说明的是有关部门对他的一种肯定,也是对直播带货行业发展的一种肯定。出了辛巴燕窝糖水事件和网红虚假卖货的老板带客户进车间,两名员工正在吵架,老板通知人事辞退两人,老板过分吗?你认为呢?我认为老板做事有些过分了,而且处理事情太过武断直接,更为重要的是如此行事属于越权指挥,实数不妥,这损害的其实是公司的制度管理。所以我不认可老板的做法。在我看来,老板带客户参观车间,有一个好妈妈对孩子有多大的影响?一个好妈妈,首先自己要乐观,阳光,开朗!父母是孩子的第一任老师,父母的一言一行影响着孩子!乐观的妈妈培养的孩子也是乐观向上的!有了积极的性格,在以后的学习和工作中,遇到困难,遇到挫孩子早晨起来就耍脾气怎么办?孩子早晨起来就耍脾气怎么办表扬和鼓励孩子不要总是批评孩子,要尽可能多地鼓励和表扬孩子。例如,如果孩子今天发脾气少了,家长要及时表扬,这样孩子就会得到鼓励,为了家长的表扬,会尽可能控如何评价毛晓彤?我喜欢毛晓彤,她坚强中带着一丝随性,处事淡然却又不任人欺辱。温柔甜美的外表加之俏皮灵动的形象,就是我心中最美的女神。毛晓彤毕业于中央戏剧学院,凭借过硬的实力强势踏入演艺圈,一部甄嬛绝地求生腰射和肩射哪一个比较容易打到人?很多时候我们近距离作战会放弃开镜射击这一种射击方式而去选择肩射或腰射,那么到底哪一个更容易打到人呢?首先我们需要弄清楚他们的区别。1。腰射,腰射是通过直接按鼠标左键开枪而不做其他动
小程序丨焕然升级!重新认识吧,解锁更多精彩QWOWO小程序更新啦!全新板块等你来探索,一键GET趣味体验。QWOWO小程序发现功能开启啦!升级焕新,多种功能,邀你一同感受IP乐趣。新功能涵盖三大板块,将给大家带来更有趣的新蔡天凤案波及电视剧!吃软饭故事破产,不少名媛艺人不敢置信文区汉宗香港时尚界28岁名媛蔡天凤遭邝姓前夫一家共谋杀害,这家人为了掩人耳目,甚至凶残地将蔡天凤尸体肢解,还将其遗体烹煮成人肉汤,企图毁尸灭迹。消息曝光后震惊整个华人社会。蔡天凤案各种预算都是够,从600多元到2万,11种价位共39款海信电视()大家好啊,祝大家发大财,事业顺利,感情和睦,阖家欢乐,身体健康,福禄寿增长。在这个气温舒适的时节,选一个大屏看看电视,比如吃着零食,喝着茶,看着电视,或者来几局欢乐的游戏,那无电视不再古板!这款灵控桌面让你媲美手机体验感市场上电视机类型层出不穷,然而真正满足用户需求且可以让人们做到放下手机的电视又有几个呢?相信大家都有经历过,打开电视随意划拉了几下,满屏五花八门的分类和推广让人瞬间没有看下去的欲望电视观影神器TVBOX之二直播,点播一应俱全因为上一次发的被无缘无故戴了顶帽子,已不能被推荐,这里重发一遍。内容基本一致。TVBox是github上的一款优秀的开源项目,也正因为如此,基于此项目而衍生出的资源配置接口也是层出肖战被吐槽似乡村老干部,代表亚洲荣登意大利电视台,看2场走秀肖战造型酷似乡村老干部,代表亚洲荣登意大利电视台,受邀观看2场!肖战米兰时装周其中一条造型曝光,米色外套搭配同色系针织内搭,尽显温柔暖男气质!也有网友表示肖战丑到我了!这完全把米兰深圳创投日兔年首站走进罗湖落地6支产业基金总规模逾260亿元近日,深圳创投日兔年首站走进罗湖,以蝶变红岭创见未来为主题,展现了全市重点金融集聚区红岭新兴金融产业带的蝶变新颜,围绕高规格打造国际财富管理中心重磅发布首个区级支持政策和五大金融产中美芯片大对决!中国研发碳基芯片,能否让中国芯换道超车?芯片作为电子产品的心脏,每年全球的芯片需求达到了万亿颗,但是随着传统硅基芯片的不断发展,芯片性能已接近极限,于是我国决定启用新材料碳纳米管,以此来研发碳基芯片。那这个碳基芯片有什么艾利和桌面系统的执着,CA1000升T了!又到了回顾HiFi新品的老时间,来看看有哪些鲜货吧01艾利和新品台机发售ACROCA1000T,16888元艾利和ACROCA1000TACROCA1000T采用两颗ESS旗舰级EOTA终于!小米12SUltra新增2X快捷开关史诗级更新发布于去年7月的小米12SUltra,曾多次被用户催更能否给拍照主界面增加一个2X的快捷开关,在小米13系列发布后一度以为12SUltra应该不会上这个开关了,没想到近日小米终于想别再披头散发了,这3种人扎头发,比披发更显脸小我发现很多姐妹都会觉得自己脸型五官不够完美,就天天披头散发,以为这样就能把我们脸部的缺点全遮住,就是最显脸小的方法。非也非也。相反有些问题脸型,扎发会明显比披发显脸小好看很多。不信