翼度科技»论坛 编程开发 python 查看内容

【日常收支账本】【Day05】编辑账本界面增加删除、更新记录功能——提高代

5

主题

5

帖子

15

积分

新手上路

Rank: 1

积分
15
一、项目地址

https://github.com/LinFeng-BingYi/DailyAccountBook
二、新增

1. 增加删除记录功能

1.1 功能详述



  • 点击删除按钮后,获取对应行的数据组成字典,用字典的键值对匹配到对应日期的记录元素;
  • 接着用该字典数据冲正存款账户余额(实现思路为新增记录时的反向操作),同时删除记录元素;
  • 最后再更新表格。
1.2 代码实现
  1.     def deleteTableRow(self, triggeredBtn, tableWidget):
  2.         print("触发了删除按钮")
  3.         # 获取触发信号的控件所在行号
  4.         current_row = tableWidget.indexAt(triggeredBtn.parent().pos()).row()
  5.         if tableWidget == self.tableWidget_expense:
  6.             const_class = expenseConst
  7.             action = 'expense'
  8.         elif tableWidget == self.tableWidget_income:
  9.             const_class = incomeConst
  10.             action = 'income'
  11.         elif tableWidget == self.tableWidget_movement:
  12.             const_class = movementConst
  13.             action = 'movement'
  14.         else:
  15.             print('未知控件触发新增按钮!')
  16.             return
  17.         # 获取待删除行的数据
  18.         old_data_dict = self.getExistTableCell(tableWidget, current_row, const_class)
  19.         if old_data_dict is None:
  20.             print("获取待删除数据失败!!")
  21.             return
  22.         print("待删除记录内容为: \n", old_data_dict)
  23.         if self.file_processor.deleteRecord(old_data_dict, self.dateEdit.text().replace('/', ''), action):
  24.             print("删除成功!")
  25.             # 把删除结果写入文件
  26.             self.file_processor.writeXMLFile(self.lineEdit_file_path.text())
  27.             # 更新self.file_parse_result以及记录表
  28.             records_list = self.file_parse_result[action + 's']
  29.             records_list.pop(current_row)
  30.             self.updateRecordTable(tableWidget, records_list, const_class)
复制代码
其中处理xml文件的方法代码如下:
  1.     def deleteRecord(self, old_record_dict, date_str, action):
  2.         e_date = self.getSpecificDateElement(date_str)
  3.         if isinstance(e_date, int):
  4.             print("未找到这一天的数据!")
  5.             return False
  6.         if action == 'expense':
  7.             action_path = ".//expenses"
  8.             record_path = """.//expense[@necessity='{}'][@associatedFund='{}'][value='{}'][category='{}'][detail='{}'][describe='{}'][from='{}']""".format(
  9.                 old_record_dict['necessity'],
  10.                 old_record_dict['associatedFund'],
  11.                 old_record_dict['value'],
  12.                 old_record_dict['category'],
  13.                 old_record_dict['detail'],
  14.                 old_record_dict['describe'],
  15.                 old_record_dict['from'])
  16.         elif action == 'income':
  17.             action_path = ".//incomes"
  18.             record_path = """.//income[@associatedFund='{}'][value='{}'][category='{}'][detail='{}'][describe='{}'][to='{}']""".format(
  19.                 old_record_dict['associatedFund'],
  20.                 old_record_dict['value'],
  21.                 old_record_dict['category'],
  22.                 old_record_dict['detail'],
  23.                 old_record_dict['describe'],
  24.                 old_record_dict['to'])
  25.         elif action == 'movement':
  26.             action_path = ".//movements"
  27.             record_path = """.//movement[value='{}'][detail='{}'][describe='{}'][from='{}'][to='{}']""".format(
  28.                 old_record_dict['value'],
  29.                 old_record_dict['detail'],
  30.                 old_record_dict['describe'],
  31.                 old_record_dict['from'],
  32.                 old_record_dict['to'])
  33.         else:
  34.             print("未知的动账操作!!")
  35.             return False
  36.         # print(record_path)
  37.         e_action = e_date.find(action_path)
  38.         e_record = e_action.find(record_path)
  39.         if e_record is None:
  40.             print("未找到待删除的记录")
  41.             return False
  42.         e_action.remove(e_record)
  43.         if action == 'movement':
  44.             self.modifyBalance(old_record_dict['from'], Decimal(old_record_dict['value']))
  45.             self.modifyBalance(old_record_dict['to'], Decimal(old_record_dict['value']) * (-1))
  46.         else:
  47.             self.reversalVariation(old_record_dict, e_date)
  48.         return True
  49.     def reversalVariation(self, change_dict, e_date):
  50.         """
  51.         Describe: 删除某条记录时,需要冲正原来的记录,将回退对应的存款账户数值变化、以及余额
  52.         Args:
  53.             change_dict: dict
  54.                 记录字典
  55.             e_date: Element
  56.                 指定日期的day元素
  57.         """
  58.         e_variation = e_date.find(".//variation")
  59.         if e_variation is None:
  60.             print("冲正记录时异常!!该记录不存在余额变化")
  61.             return
  62.         if 'from' in change_dict:
  63.             e_fund_variety = e_variation.find(".//fund[category='{}']/out".format(change_dict['from']))
  64.             if e_fund_variety is None:
  65.                 print("冲正记录时异常!!该记录不存在余额变化")
  66.                 return
  67.             e_fund_variety.text = str((Decimal(e_fund_variety.text) - Decimal(change_dict['value'])).quantize(Decimal('0.00')))
  68.             self.modifyBalance(change_dict['from'], Decimal(change_dict['value']))
  69.             self.reversalAssociatedFund(e_variation, change_dict, 'from')
  70.         if 'to' in change_dict:
  71.             e_fund_variety = e_variation.find(".//fund[category='{}']/in".format(change_dict['to']))
  72.             if e_fund_variety is None:
  73.                 print("冲正记录时异常!!该记录不存在余额变化")
  74.                 return
  75.             e_fund_variety.text = str((Decimal(e_fund_variety.text) - Decimal(change_dict['value'])).quantize(Decimal('0.00')))
  76.             self.modifyBalance(change_dict['to'], Decimal(change_dict['value'])*(-1))
  77.             self.reversalAssociatedFund(e_variation, change_dict, 'to')
  78.     def reversalAssociatedFund(self, e_variation, change_dict, from_or_to):
  79.         """
  80.         Describe: 冲正关联账户
  81.         Args:
  82.             e_variation: Element
  83.             change_dict: dict
  84.             from_or_to: ['from', 'to']
  85.         """
  86.         # print(change_dict['associatedFund'])
  87.         if 'associatedFund' in change_dict and change_dict['associatedFund'] != 'None':
  88.             print('执行了associatedFund冲正,操作为', from_or_to)
  89.             if e_variation.find(".//fund[category='{}']".format(change_dict['associatedFund'])) is None:
  90.                 print("冲正记录时异常!!该记录不存在关联账户余额变化")
  91.                 return
  92.             if from_or_to == 'from':
  93.                 e_fund_variety = e_variation.find(".//fund[category='{}']/out".format(change_dict['associatedFund']))
  94.                 flag = 1
  95.             elif from_or_to == 'to':
  96.                 e_fund_variety = e_variation.find(".//fund[category='{}']/in".format(change_dict['associatedFund']))
  97.                 flag = -1
  98.             else:
  99.                 print('未知的收支动作!')
  100.                 return
  101.             e_fund_variety.text = str((Decimal(e_fund_variety.text) - Decimal(change_dict['value'])).quantize(Decimal('0.00')))
  102.             self.modifyBalance(change_dict['associatedFund'], Decimal(change_dict['value'])*flag)
复制代码
2. 增加更新记录功能

2.1 功能详述



  • 点击更新按钮后,获取对应行的数据组成新记录字典;
  • 同时根据行号获取编辑账本界面的self.file_parse_result属性对应的旧记录字典(每次更新xml文件时,该属性都会同步);
  • 接着用旧字典数据冲正存款账户余额(实现思路为新增记录时的反向操作),再用新字典数据更新账户余额,>- 最后再更新self.file_parse_result属性。
2.2 代码实现
  1.     def updateTableRow(self, triggeredBtn, tableWidget):
  2.         print("触发了新增按钮")
  3.         # 获取触发信号的控件所在行号
  4.         current_row = tableWidget.indexAt(triggeredBtn.parent().pos()).row()
  5.         if tableWidget == self.tableWidget_expense:
  6.             const_class = expenseConst
  7.             action = 'expense'
  8.         elif tableWidget == self.tableWidget_income:
  9.             const_class = incomeConst
  10.             action = 'income'
  11.         elif tableWidget == self.tableWidget_movement:
  12.             const_class = movementConst
  13.             action = 'movement'
  14.         else:
  15.             print('未知控件触发新增按钮!')
  16.             return
  17.         # 获取被更新的旧数据(文件解析后,记录顺序与表格顺序相同)
  18.         old_data_dict = self.file_parse_result[action+'s'][current_row]
  19.         print("旧记录内容为: \n", old_data_dict)
  20.         # 获取更新后的新数据
  21.         new_data_dict = self.getExistTableCell(tableWidget, current_row, const_class)
  22.         if new_data_dict is None:
  23.             print("获取更新后的数据失败!!")
  24.             return
  25.         print("更新后的记录内容为: \n", new_data_dict)
  26.         if self.file_processor.updateRecord(old_data_dict, new_data_dict, self.dateEdit.text().replace('/', ''), action):
  27.             print("更新成功!")
  28.             # 把删除结果写入文件
  29.             self.file_processor.writeXMLFile(self.lineEdit_file_path.text())
  30.             # 更新self.file_parse_result
  31.             self.file_parse_result[action+'s'][current_row] = new_data_dict
  32.             # print(self.file_parse_result)
复制代码
其中处理xml文件的方法代码如下:
  1.     def updateRecord(self, old_record_dict, new_record_dict, date_str, action):
  2.         e_date = self.getSpecificDateElement(date_str)
  3.         if isinstance(e_date, int):
  4.             print("未找到这一天的数据!")
  5.             return False
  6.         if action == 'expense':
  7.             action_path = ".//expenses"
  8.             record_path = """.//expense[@necessity='{}'][@associatedFund='{}'][value='{}'][category='{}'][detail='{}'][describe='{}'][from='{}']""".format(
  9.                 old_record_dict['necessity'],
  10.                 old_record_dict['associatedFund'],
  11.                 old_record_dict['value'],
  12.                 old_record_dict['category'],
  13.                 old_record_dict['detail'],
  14.                 old_record_dict['describe'],
  15.                 old_record_dict['from'])
  16.         elif action == 'income':
  17.             action_path = ".//incomes"
  18.             record_path = """.//income[@associatedFund='{}'][value='{}'][category='{}'][detail='{}'][describe='{}'][to='{}']""".format(
  19.                 old_record_dict['associatedFund'],
  20.                 old_record_dict['value'],
  21.                 old_record_dict['category'],
  22.                 old_record_dict['detail'],
  23.                 old_record_dict['describe'],
  24.                 old_record_dict['to'])
  25.         elif action == 'movement':
  26.             action_path = ".//movements"
  27.             record_path = """.//movement[value='{}'][detail='{}'][describe='{}'][from='{}'][to='{}']""".format(
  28.                 old_record_dict['value'],
  29.                 old_record_dict['detail'],
  30.                 old_record_dict['describe'],
  31.                 old_record_dict['from'],
  32.                 old_record_dict['to'])
  33.         else:
  34.             print("未知的动账操作!!")
  35.             return False
  36.         # print(record_path)
  37.         e_action = e_date.find(action_path)
  38.         e_record = e_action.find(record_path)
  39.         if e_record is None:
  40.             print("未找到待删除的记录")
  41.             return False
  42.         # 修改了数值则需要冲正
  43.         if old_record_dict['value'] != new_record_dict['value']:
  44.             # 先冲正原记录数据
  45.             # 在用新数据修改账户变化和余额
  46.             if action == 'movement':
  47.                 self.modifyBalance(old_record_dict['from'], Decimal(old_record_dict['value']))
  48.                 self.modifyBalance(old_record_dict['to'], Decimal(old_record_dict['value']) * (-1))
  49.                 self.modifyBalance(new_record_dict['from'], Decimal(new_record_dict['value']) * (-1))
  50.                 self.modifyBalance(new_record_dict['to'], Decimal(new_record_dict['value']))
  51.             else:
  52.                 self.reversalVariation(old_record_dict, e_date)
  53.                 self.organizeVariation(new_record_dict, e_date)
  54.         # 修改记录数据
  55.         for key in new_record_dict.keys():
  56.             if key == 'necessity':
  57.                 e_record.attrib['necessity'] = new_record_dict['necessity']
  58.             elif key == 'associatedFund':
  59.                 e_record.attrib['associatedFund'] = new_record_dict['associatedFund']
  60.             else:
  61.                 e_record.find(".//"+key).text = str(new_record_dict[key])
  62.         return True
复制代码
3. 优化界面控件(内置spinBox、增加按钮切换日期)

3.1 功能详述

将记录表格数值(value)列内置QSpinBox,以避免存于文件的数值小数点位不一致;增加按钮来控制日期的切换
3.2 效果展示

   
   
    数值(value)列内置QSpinBox   
   
    增加按钮来控制日期的切换3.3 代码实现
  1. # 内置QDoubleSpinBox
  2. spinBox = QDoubleSpinBox(decimals=2)# 设置保留小数后2位
  3. # 设置范围,默认为[0.0, 100.0)。必须在调整数值前设置,否则大于等于100.0时会变成99.99
  4. spinBox.setRange(0.0, 100000000.0)
  5. spinBox.setSingleStep(0.1)          # 设置步长
  6. spinBox.setValue(value)             # 调整数值
  7. tableWidget.setCellWidget(current_row, keys_list.index(key), spinBox)
  8. # 日期切换
  9. # 利用QDate类的addDays(int)方法
  10. self.pushButton_prev_day.clicked.connect(lambda: self.dateEdit.setDate(self.dateEdit.date().addDays(-1)))
  11. self.pushButton_post_day.clicked.connect(lambda: self.dateEdit.setDate(self.dateEdit.date().addDays(1)))
复制代码
三、开发总结

1. 提高代码复用性

最近几篇都没有技术含量,就不总结了。唯一值得一提的就是提高代码复用性。

  • 对于支出、收入、转移三种动账类型,字段大量重复,于是创建表格时,将所有列的初始化集中到一个函数中,根据列名执行对应初始化方式。
  • 通过设置ExpenseConst、IncomeConst、MovementConst三个具有同名常量的类,更好地支持代码复用
  • 第二章删除和新增记录时修改xml文件的方法deleteRecord(old_record_dict, date_str, action)和updateRecord(self, old_record_dict, new_record_dict, date_str, action)是通过action区分动账类型,避免同一个功能需要实现三个方法

来源:https://www.cnblogs.com/LinfengBingyi/p/17756104.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具