需求:在TableView表格中点击单元格可以实现编辑功能。性别由LineEdite控件编辑,年龄由spinBox控件编辑。

  实现:(1)使用Qt的model-view模式生成表格视图。

       (2)重写QAbstractItemDelegate类和类中的paint、createEditor、setEditorData、setModelData函数。

       (3)重写QAbstractTableModel类。

  

  功能展示:

  主要代码:

  (1)Model部分。此部分完成数据推送和数据编辑功能。

  1. class MyTableModel(QAbstractTableModel):
  2. """Model"""
  3. def __init__(self):
  4. super(MyTableModel, self).__init__()
  5. self._data = []
  6. self._background_color = []
  7. self._headers = ['学号', '姓名', '性别', '年龄']
  8.  
  9. self._generate_data()
  10.  
  11. def _generate_data(self):
  12. """填充表格数据"""
  13. name_list = ['张三', '李四', '王五', '王小二', '李美丽', '王二狗']
  14.  
  15. for id_num, name in enumerate(name_list):
  16. self._data.append([str(id_num), name, '男', str(random.randint(20, 25))])
  17.  
  18. # :默认单元格颜色为白色
  19. self._background_color.append([QColor(255, 255, 255) for i in range(4)])
  20.  
  21. def rowCount(self, parent=QModelIndex()):
  22. """返回行数量。"""
  23. return len(self._data)
  24.  
  25. def columnCount(self, parent=QModelIndex()):
  26. """返回列数量。"""
  27. return len(self._headers)
  28.  
  29. def headerData(self, section, orientation, role):
  30. """设置表格头"""
  31. if role == Qt.DisplayRole and orientation == Qt.Horizontal:
  32. return self._headers[section]
  33.  
  34. def data(self, index, role):
  35. """显示表格中的数据。"""
  36. if not index.isValid() or not 0 <= index.row() < self.rowCount():
  37. return QVariant()
  38.  
  39. row = index.row()
  40. col = index.column()
  41.  
  42. if role == Qt.DisplayRole:
  43. return self._data[row][col]
  44. elif role == Qt.BackgroundColorRole:
  45. return self._background_color[row][col]
  46. elif role == Qt.TextAlignmentRole:
  47. return Qt.AlignCenter
  48.  
  49. return QVariant()
  50.  
  51. def setData(self, index, value, role):
  52. """编辑单元格中的数据"""
  53. if not index.isValid() or not 0 <= index.row() < self.rowCount():
  54. return QVariant()
  55.  
  56. if role == Qt.EditRole:
  57. if index.column() == 2:
  58. self._data[index.row()][index.column()] = value
  59. self.layoutChanged.emit() # 更新数据后要通知表格刷新数据
  60. return True
  61. elif index.column() == 3:
  62. self._data[index.row()][index.column()] = str(value)
  63. self.layoutChanged.emit()
  64. return True
  65. else:
  66. return False
  67.  
  68. def flags(self, index):
  69. """设置单元格的属性。"""
  70. if index.column() == 0 or index.column() == 1:
  71. # :我们设置第0、1列不可编辑,其他列可以编辑。
  72. return super().flags(index)
  73.  
  74. return Qt.ItemIsEditable | super().flags(index)

  (2)Delegate部分。此部分完成View中数据的展示,以及单元格中编辑器的生成、编辑器内容的推送和编辑器内容更新到Model。

  1. class MyDelegate(QAbstractItemDelegate):
  2. """Delegate"""
  3. def __init__(self):
  4. super(MyDelegate, self).__init__()
  5.  
  6. def paint(self, painter, option, index):
  7. """绘制单元格。"""
  8. if index.column() == 0:
  9. # :表格第一列是ID,单元格中绘制一个图片和ID。
  10. p = QStyleOptionViewItem()
  11. p.index = index
  12. p.rect = option.rect
  13. p.features = QStyleOptionViewItem.HasDecoration | QStyleOptionViewItem.HasDisplay
  14. p.text = str(index.data())
  15. p.decorationSize = QSize(44, 44) # 设置装饰图标的大小。
  16. p.icon = QIcon('../image/id.png') # 设置装饰图标路径名
  17. p.state = option.state
  18. p.showDecorationSelected = True # 开启选中时,单元格高亮显示
  19. # :若项目被选择,则高亮绘制其矩形
  20.  
  21. p.decorationPosition = QStyleOptionViewItem.Left # 图片在文字的左边
  22. p.displayAlignment = Qt.AlignLeft | Qt.AlignCenter # 设置文字的位置
  23. QApplication.style().drawControl(QStyle.CE_ItemViewItem, p, painter)
  24. else:
  25. # :向表格中渲染数据,如果缺少下面代码,表格中数据不能正常显示。
  26. # :这里应该在model的data函数之后调用,此时通过index可以获取要显示。
  27. # :的数据。
  28. p = QStyleOptionViewItem()
  29. p.features = QStyleOptionViewItem.HasDisplay
  30. p.index = index # 表格QModelIndex索引
  31. p.rect = option.rect
  32. p.state = option.state
  33.  
  34. p.showDecorationSelected = True # 开启选中时,单元格高亮显示
  35. p.text = str(index.data()) # 表格中的数据
  36. QApplication.style().drawControl(QStyle.CE_ItemViewItem, p, painter)
  37.  
  38. def createEditor(self, parent, option, index):
  39. """给单元格创建编辑器(点击单元格的时候调用)"""
  40. if index.column() == 2:
  41. # :第2列性别设置为lineEdite编辑器。
  42. # :注意,在创建编辑控件的时候传入parent防止在编辑时新弹出窗口来进行编辑。
  43. p = QLineEdit(parent)
  44. p.setFocusPolicy(Qt.TabFocus)
  45. # :设置控件的位置,如果忽略此句,控件会出现在窗体的左上角。
  46. p.setGeometry(option.rect)
  47. return p
  48. elif index.column() == 3:
  49. # :第3列年龄设置为spinBox编辑器。
  50. p = QSpinBox(parent)
  51. p.setMaximum(150) # 年龄最大值为150
  52. p.setGeometry(option.rect)
  53. return p
  54. else:
  55. return super().createEditor(parent, option, index)
  56.  
  57. def setEditorData(self, editor, index):
  58. """把model中的数据填充到编辑器当中(点击单元格的时候调用但晚于createEditor)"""
  59. if index.column() == 2:
  60. # :lineEdit编辑器。
  61. editor.setText(index.data())
  62. elif index.column() == 3:
  63. editor.setValue(int(index.data()))
  64. else:
  65. super().setEditorData(editor, index)
  66.  
  67. def setModelData(self, editor, model, index):
  68. """把编辑器中的数据更新到model当中(编辑完成时调用)"""
  69. if index.column() == 2:
  70. model.setData(index, editor.text(), role=Qt.EditRole)
  71. elif index.column() == 3:
  72. model.setData(index, editor.value(), role=Qt.EditRole)
  73. else:
  74. super().setModelData(editor, model, index)

  Demo源码:

  Demo源码参考网址(码云):https://gitee.com/cui_zhen/pyqt5-example

Pyqt5——表格中隐藏的控件(Model/View/Delegate)的更多相关文章

  1. 在VisualStudio 工具箱中隐藏用户控件

    当我们创建一个用户控件后,VisualStudio会自动将其添加到工具箱中,本来这是一个比较贴心的设计.但是,有的时候,我们并不想将用户控件放到工具箱中. 例如:在WPF中,为了避免一个页面的控件过多 ...

  2. 重写UITableViewCell子类中属性的setter方法来实现隐藏或显示该cell中的某些控件

    重写UITableViewCell子类中属性的setter方法来实现隐藏或显示该cell中的某些控件 为什么会需要这样子的一种方法来实现隐藏或者显示一个cell中的某些控件呢? 其实,隐藏cell中某 ...

  3. (转)客户端触发Asp.net中服务端控件事件

    第一章. Asp.net中服务端控件事件是如何触发的 Asp.net 中在客户端触发服务端事件分为两种情况: 一. WebControls中的Button 和HtmlControls中的Type为su ...

  4. 转:ExpressBars中的停靠控件使用

    http://www.cnblogs.com/jxsoft/archive/2011/08/25/2152872.html 1          新手上路 1.1      控件简介 Dock pan ...

  5. ASP.NET中 WebForm 窗体控件使用及总结【转】

    原文链接:http://www.cnblogs.com/ylbtech/archive/2013/03/06/2944675.html ASP.NET中 WebForm 窗体控件使用及总结. 1.A, ...

  6. HTML5 Web app开发工具Kendo UI Web中Grid网格控件的使用

    Kendo UI Web中的Grid控件不仅可以显示数据,并对数据提供了丰富的支持,包括分页.排序.分组.选择等,同时还有着大量的配置选项.使用Kendo DataSource组件,可以绑定到本地的J ...

  7. android中的EditView控件

    android中的EditView控件 EditText继承关系:View-->TextView-->EditText ,EditText是可编辑文本框 1.EditText默认情况下,光 ...

  8. android中的TextView控件

    我以前是搞ssh开发的,现在在搞android开发,所以简单学习了一下,对于自己所了解的做一个记录,也算是一个笔记吧,如果有什么不对的,希望大家给予一定的指导.  一.TextView的基本使用 Te ...

  9. TWaver初学实战——如何在TWaver属性表中添加日历控件?

    在日期输入框中添加日历控件,是一种非常流行和实用的做法.临渊羡鱼不如退而写代码,今天就看看在TWaver中是如何实现的.   资源准备   TWaver的在线使用文档中,就有TWaver Proper ...

随机推荐

  1. Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2) E. Let Them Slide(数据结构+差分)

     题意:问你有n个长度总和为n的数组 你可以移动数组 但不能移出长度为w的矩形框 问你每一列的最大值是多少? 思路:只有一次询问 我们可以考虑差分来解决 然后对于每一行数组 我们可以用数据结构维护一下 ...

  2. 【洛谷 p3383】模板-线性筛素数(数论)

    题目:给定一个范围N,你需要处理M个某数字是否为质数的询问(每个数字均在范围1-N内).(N<=10000000,M<=100000) 解法:1.欧拉筛O(n),数组近乎100KB:2.( ...

  3. 【洛谷 p3379】模板-最近公共祖先(图论--倍增算法求LCA)

    题目:给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 解法:倍增. 1 #include<cstdio> 2 #include<cstdlib> 3 #include ...

  4. Codeforces Round #649 (Div. 2) C. Ehab and Prefix MEXs

    题目链接:https://codeforces.com/contest/1364/problem/C 题意 给出大小为 $n$ 的非递减数组 $a$,构造同样大小的数组 $b$,使得对于每个 $i$, ...

  5. 【noi 2.5_7834】分成互质组(dfs)

    有2种dfs的方法: 1.存下每个组的各个数和其质因数,每次对于新的一个数,与各组比对是否互质,再添加或不添加入该组. 2.不存质因数了,直接用gcd,更加快.P.S.然而我不知道为什么RE,若有好心 ...

  6. hdu5437 Alisha’s Party

    Problem Description Princess Alisha invites her friends to come to her birthday party. Each of her f ...

  7. CF1400-D. Zigzags

    CF1400-D. Zigzags 题意: 给出一个由\(n\)个数字构成的数组\(a\),让你在这个数组中找出有多少个符合以下要求的元组\((i,j,k,l)\): 1. \(i<j<k ...

  8. K8S(05)核心插件-ingress(服务暴露)控制器-traefik

    K8S核心插件-ingress(服务暴露)控制器-traefik 1 K8S两种服务暴露方法 前面通过coredns在k8s集群内部做了serviceNAME和serviceIP之间的自动映射,使得不 ...

  9. 二进制安装kubernetes(七) 部署知识点总结

    1.k8s各个组件之间通信,在高版本中,基本都是使用TSL通信,所以申请证书,是必不可少的,而且建议使用二进制安装,或者在接手一套K8S集群的时候,第一件事情是检查证书有效期,证书过期或者TSL通信问 ...

  10. 2.使用Helm构建ElasticSearch集群

    作者 微信:tangy8080 电子邮箱:914661180@qq.com 更新时间:2019-05-24 16:08:53 星期五 欢迎您订阅和分享我的订阅号,订阅号内会不定期分享一些我自己学习过程 ...