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

香,一套逻辑轻松且智能解决PyQt中控件数值验证的问题

8

主题

8

帖子

24

积分

新手上路

Rank: 1

积分
24
在PyQt开发中,时常需要对控件的值进行校验,如需要校验QCheckBox是否被选中,QLabel是否校验值是否为空等等。在复杂的业务场景下,这类控件如果数量很多,逐个校验就显得麻烦,需要一一获得控件名称,再调用对应的方法来判断是否被选中、是否为空等。而且开发过程中如果多控件做了增减,还需要增减校验的逻辑,那会要了老命。
此篇文章,推荐使用__dict__属性 + 字典映射来快速校验控件值,并且无视后面控件的增减,无需调整代码。
__dict__是什么?

做python开发的,或多或少都接触过该属性,它是类独有的一个特性,用来保存类的一些属性,关于这个属性的相关文章,网上一抓一大把,此处不作赘述,需要说明的是,类实例也有自己的__dict__属性,而且和类的__dict不同,``类实例的dict只保存了通过self.xxx`所声明的属性和方法。
校验逻辑演示

接下来的演示中,仅使用QCheckBox(为了省事),同时要保持这些控件的名称要具备同样的特征,下面的截图中,所有的控件名称都以checkbox结尾。
1、使用.ui文件生成.py文件
2、简单写个入口程序
继承刚才生成的.py文件,在这里可以实现自己的方法,在自定义类中,先打印__dict__,看看有哪些值。
  1. {
  2.   'centralwidget': <PyQt6.QtWidgets.QWidget object at 0x00000231DD4E9D30>,
  3.   'gridLayout': <PyQt6.QtWidgets.QGridLayout object at 0x00000231DD4E9DC0>,
  4.   'c_checkbox': <PyQt6.QtWidgets.QCheckBox object at 0x00000231DD4E9E50>,
  5.   'd_checkbox': <PyQt6.QtWidgets.QCheckBox object at 0x00000231DD4E9EE0>,
  6.   'a_checkbox': <PyQt6.QtWidgets.QCheckBox object at 0x00000231DD4E9F70>,
  7.   'b_checkbox': <PyQt6.QtWidgets.QCheckBox object at 0x00000231DD9A3040>,
  8.   'f_checkbox': <PyQt6.QtWidgets.QCheckBox object at 0x00000231DD9A30D0>,
  9.   'e_checkbox': <PyQt6.QtWidgets.QCheckBox object at 0x00000231DD9A3160>,
  10.   'menubar': <PyQt6.QtWidgets.QMenuBar object at 0x00000231DD9A31F0>,
  11.   'statusbar': <PyQt6.QtWidgets.QStatusBar object at 0x00000231DD9A3280>
  12. }
复制代码
可以看到,它是一个字典,它包含了界面上所有的控件的名称和实例对象,这里就体现出了控件名称命名时遵守统一特征的好处了,即能望文生义,也方便处理。
3、提取所有QCheckBox的控件名称,构建一个校验的通用逻辑
  1. import sys
  2. from PyQt6.QtWidgets import QMainWindow, QApplication, QCheckBox
  3. from ui_main import Ui_MainWindow
  4. class MainWindow(Ui_MainWindow, QMainWindow):
  5.     def __init__(self):
  6.         super().__init__()
  7.         super().setupUi(self)
  8.         self.show()
  9.         self.checkboxs()
  10.    
  11.     def checkboxs(self):
  12.         # print(self.__dict__)
  13.         # 增加这个字典映射是为了可以自动处理更多类型的控件值校验
  14.         widget_mapping = {
  15.             'QCheckBox': QCheckBox.isChecked
  16.         }
  17.         
  18.         # 获取所有QCheckBox的控件名称
  19.         boxs = [
  20.             item for item in self.__dict__ \
  21.                 if item.endswith('_checkbox')
  22.         ]
  23.         # 用来保存未被勾选的控件
  24.         un_checked = []
  25.         for item in boxs:
  26.             widget_instance = self.__dict__.get(item)
  27.             widget_method = widget_mapping.get(
  28.                 self.__dict__.get(item).__class__.__name__
  29.             )
  30.             # 如果该QCheckBox处于未选中,则被添加到列表中
  31.             if not widget_method(widget_instance):
  32.                 un_checked.append(item)
  33.         print(un_checked)
  34. if __name__ == '__main__':
  35.     app = QApplication(sys.argv)
  36.     window = MainWindow()
  37.     sys.exit(app.exec())
复制代码
4、逻辑分析
(1)
在代码
  1. boxs = [
  2.             item for item in self.__dict__ \
  3.                 if item.endswith('_checkbox')
  4.         ]
复制代码
中,通过__dict__提取了所有以_checkbox结尾的控件名称,注意,这只是字符串而已,并非控件本身。
(2)构建一个通用的控件名称和控件方法的字典映射
  1. # 增加这个字典映射是为了可以自动处理更多类型的控件值校验
  2.         widget_mapping = {
  3.             'QCheckBox': QCheckBox.isChecked
  4.         }
复制代码
这么做的目的是为了让这个逻辑更具通用性,让这个逻辑兼容其他控件,简单来说,可以通过控件的名称(boxs列表)找到该控件对应的方法,因为每个控件获取值所用的方法不尽相同。
(3)遍历boxs列表,逐个去widget_mapping找对应的方法,假如这里要较多种控件的话,字典映射的优势就体现出来了。widget_method就是该控件获取值所要用的方法了,QCheckBox控件,就用isChecked方法来获取控件是否被选中。
(4)调用所找到的方法widget_method。这里之所以要把控件实例widget_instance传入方法中,是因为控件方法isChecked是单独调用的,它默认要传入self参数即实例本身。
运行代码看看效果
可以看到6个选项均为选中,打印结果符合该事实。
在qt desinger中默认勾选两个,再试试效果
有4个未选中,打印结果符合事实。
总结

上面的仅为演示代码,只是演示处理此类问题的逻辑,刚构建逻辑时会显得很绕,但是构建起来后就很好用了,如果再渐增控件,只要遵守控件名称命名规范,那么所增加的控件校验也无需增加校验代码,减少控件也一样。
延申用法

如果一个界面中有很多控件需要填写数值或清空数值,如:

  • 提交表单后,控件数值初始化
  • 校验不通过,需要在控件中做信息提示(诸如placeholder)
一样可以使用这个逻辑进行处理,只要前期构建好,代码复用完全不是问题。

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

举报 回复 使用道具