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

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

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

       (3)重写QAbstractTableModel类。

  

  功能展示:

  主要代码:

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

class MyTableModel(QAbstractTableModel):
"""Model"""
def __init__(self):
super(MyTableModel, self).__init__()
self._data = []
self._background_color = []
self._headers = ['学号', '姓名', '性别', '年龄'] self._generate_data() def _generate_data(self):
"""填充表格数据"""
name_list = ['张三', '李四', '王五', '王小二', '李美丽', '王二狗'] for id_num, name in enumerate(name_list):
self._data.append([str(id_num), name, '男', str(random.randint(20, 25))]) # :默认单元格颜色为白色
self._background_color.append([QColor(255, 255, 255) for i in range(4)]) def rowCount(self, parent=QModelIndex()):
"""返回行数量。"""
return len(self._data) def columnCount(self, parent=QModelIndex()):
"""返回列数量。"""
return len(self._headers) def headerData(self, section, orientation, role):
"""设置表格头"""
if role == Qt.DisplayRole and orientation == Qt.Horizontal:
return self._headers[section] def data(self, index, role):
"""显示表格中的数据。"""
if not index.isValid() or not 0 <= index.row() < self.rowCount():
return QVariant() row = index.row()
col = index.column() if role == Qt.DisplayRole:
return self._data[row][col]
elif role == Qt.BackgroundColorRole:
return self._background_color[row][col]
elif role == Qt.TextAlignmentRole:
return Qt.AlignCenter return QVariant() def setData(self, index, value, role):
"""编辑单元格中的数据"""
if not index.isValid() or not 0 <= index.row() < self.rowCount():
return QVariant() if role == Qt.EditRole:
if index.column() == 2:
self._data[index.row()][index.column()] = value
self.layoutChanged.emit() # 更新数据后要通知表格刷新数据
return True
elif index.column() == 3:
self._data[index.row()][index.column()] = str(value)
self.layoutChanged.emit()
return True
else:
return False def flags(self, index):
"""设置单元格的属性。"""
if index.column() == 0 or index.column() == 1:
# :我们设置第0、1列不可编辑,其他列可以编辑。
return super().flags(index) return Qt.ItemIsEditable | super().flags(index)

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

class MyDelegate(QAbstractItemDelegate):
"""Delegate"""
def __init__(self):
super(MyDelegate, self).__init__() def paint(self, painter, option, index):
"""绘制单元格。"""
if index.column() == 0:
# :表格第一列是ID,单元格中绘制一个图片和ID。
p = QStyleOptionViewItem()
p.index = index
p.rect = option.rect
p.features = QStyleOptionViewItem.HasDecoration | QStyleOptionViewItem.HasDisplay
p.text = str(index.data())
p.decorationSize = QSize(44, 44) # 设置装饰图标的大小。
p.icon = QIcon('../image/id.png') # 设置装饰图标路径名
p.state = option.state
p.showDecorationSelected = True # 开启选中时,单元格高亮显示
# :若项目被选择,则高亮绘制其矩形 p.decorationPosition = QStyleOptionViewItem.Left # 图片在文字的左边
p.displayAlignment = Qt.AlignLeft | Qt.AlignCenter # 设置文字的位置
QApplication.style().drawControl(QStyle.CE_ItemViewItem, p, painter)
else:
# :向表格中渲染数据,如果缺少下面代码,表格中数据不能正常显示。
# :这里应该在model的data函数之后调用,此时通过index可以获取要显示。
# :的数据。
p = QStyleOptionViewItem()
p.features = QStyleOptionViewItem.HasDisplay
p.index = index # 表格QModelIndex索引
p.rect = option.rect
p.state = option.state p.showDecorationSelected = True # 开启选中时,单元格高亮显示
p.text = str(index.data()) # 表格中的数据
QApplication.style().drawControl(QStyle.CE_ItemViewItem, p, painter) def createEditor(self, parent, option, index):
"""给单元格创建编辑器(点击单元格的时候调用)"""
if index.column() == 2:
# :第2列性别设置为lineEdite编辑器。
# :注意,在创建编辑控件的时候传入parent防止在编辑时新弹出窗口来进行编辑。
p = QLineEdit(parent)
p.setFocusPolicy(Qt.TabFocus)
# :设置控件的位置,如果忽略此句,控件会出现在窗体的左上角。
p.setGeometry(option.rect)
return p
elif index.column() == 3:
# :第3列年龄设置为spinBox编辑器。
p = QSpinBox(parent)
p.setMaximum(150) # 年龄最大值为150
p.setGeometry(option.rect)
return p
else:
return super().createEditor(parent, option, index) def setEditorData(self, editor, index):
"""把model中的数据填充到编辑器当中(点击单元格的时候调用但晚于createEditor)"""
if index.column() == 2:
# :lineEdit编辑器。
editor.setText(index.data())
elif index.column() == 3:
editor.setValue(int(index.data()))
else:
super().setEditorData(editor, index) def setModelData(self, editor, model, index):
"""把编辑器中的数据更新到model当中(编辑完成时调用)"""
if index.column() == 2:
model.setData(index, editor.text(), role=Qt.EditRole)
elif index.column() == 3:
model.setData(index, editor.value(), role=Qt.EditRole)
else:
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. cf 1305 E. Kuroni and the Score Distribution

    题目传送门:E. Kuroni and the Score Distribution 题目大意:给n和m,输出n个数,这些数里必须要有m对a[i]+a[j]==a[k]  ( i < j < ...

  2. poj1821 Fence(dp,单调队列优化)

    题意: 由k(1 <= K <= 100)个工人组成的团队应油漆围墙,其中包含N(1 <= N <= 16 000)个从左到右从1到N编号的木板.每个工人i(1 <= i ...

  3. POJ 2195 & HDU 1533 Going Home(最小费用最大流)

    这就是一道最小费用最大流问题 最大流就体现到每一个'm'都能找到一个'H',但是要在这个基础上面加一个费用,按照题意费用就是(横坐标之差的绝对值加上纵坐标之差的绝对值) 然后最小费用最大流模板就是再用 ...

  4. Navicat 快捷键 for Mysql

     常用快捷键: 1. ctrl + q: 打开新查询窗口 2. ctrl + r: 运行当前窗口内的所有语句 3. ctrl + w: 关闭当前窗口 4. F6: 打开一个MySQL命令行窗口 5. ...

  5. Java进阶专题(二十五) 分布式锁原理与实现

    前言 ​ 现如今很多系统都会基于分布式或微服务思想完成对系统的架构设计.那么在这一个系统中,就会存在若干个微服务,而且服务间也会产生相互通信调用.那么既然产生了服务调用,就必然会存在服务调用延迟或失败 ...

  6. python 迭代器 iter多次消费

    问题 Python 中的迭代器是我们经常使用的迭代工具, 但其只能消费一次,再次消费便会出现 StopIteration 报错. 解决方案 封装了一个类,当迭代器使用完后再次初始化. 代码 class ...

  7. 阿里云 MaxCompute(ODPS)

    大数据产品架构 BASE - Dataworks ODPS - MaxCompute ODPS 功能组成(Open Data Process Service) ODPS 是旧称,阿里云公有云服务中现称 ...

  8. 微服务架构Day05-SpringBoot之Servlet

    旧版 配置嵌入式Servlet容器 SpringBoot默认使用Tomcat作为嵌入式Servlet容器 如何定制和修改Servlet容器相关配置 1.在配置文件中定制和修改Servlet容器有关的配 ...

  9. 解决springmvc使用@ResponseBody返回String类型字符串中文乱码问题

    问题分析: 首先: 确定的是只有当返回值是 String时才会出现中文乱码,而当返回值是Map<String, Object>或者是其它类型时,并没有中文乱码的出现. 然后找原因: 原因是 ...

  10. MBP 屏幕分辨率 All In One

    MBP 屏幕分辨率 All In One screen size bug https://stackoverflow.com/questions/65462643/how-to-get-the-rea ...