PyQt5自定义QTableView

前言

为了整体界面的整洁,有些内容必须得折在界面中,使用户更关注QTableView的报表。这就意味着,QTableView需要自定义。

表头自定义

表头的自定义主要是通过继承QHeaderView,并实现其中的功能。目前遇到的需求是,点击表头实现筛选。就比如,我现在在TableView中显示的是abcd,点击a之后,需要去数据库中查询t表里面的字段a的所有值。

听起来复杂,实现起来又该如何呢?

首先创建表头:

1
2
3
class CustomHeader(QHeaderView):
def __init__(self, orientation, parent=None):
super(CustomHeader, self).__init__(orientation, parent)

但可惜的是,表头本身并不能设置内容,需要设置表头显示内容只能通过QTableView中的QStandardModel

那么也就只能够曲线救国:点击表头返回点击的索引,再通过QStandardModel去访问该索引下的内容。于是,我们先设置表头可点击:

1
2
3
4
class CustomHeader(QHeaderView):
def __init__(self, orientation, parent=None):
super(CustomHeader, self).__init__(orientation, parent)
self.setSectionsClickable(True)

点击了之后呢?在当前项目中,QHeaderView本身一定会是QTableView的子组件,所以直接采用子组件向上传递信号的方法,也就是利用parent属性访问到QTableView的专有属性。

1
2
def on_section_clicked(self, index):
self.parent().highlightedColumn = index

最后,设置点击就触发:

1
2
3
4
5
class CustomHeader(QHeaderView):
def __init__(self, orientation, parent=None):
super(CustomHeader, self).__init__(orientation, parent)
self.setSectionsClickable(True)
self.sectionClicked.connect(self.on_section_clicked)

表头自定义就到此结束了。

表格自定义

那么接下来就开始自定义表格了。首先将表头放入表格的内部?不不不,别急。我们先确定表格需要做什么。

1
2
3
4
5
class CustomTableView(QTableView):
def __init__(self, parent=None):
super().__init__(parent)
# 用于跟踪从`QHeaderView`中点击的索引
self.highlightedColumn = -1

当然,我们的事件是定义在表头的,并不是表格的。所以当表头被点击的时候,self.highlightedColumn变量就已经出现变化了。所以,接下来并不需要刻意去担心什么别的东西。接下来就是具体到通过索引获取到表头具体是什么内容了。

那么,我们表头的数据既然是在QStandardModel中设置,那也就是在QStandardModel中获取咯?没毛病。但我现在是QTableView诶,这个可不一样哦。那该怎么办呢?

没关系。我们依然可以通过model()方法获取QTableView中的数据,然后再通过headerData方法获取就好了。

1
2
3
def get_clicked_column_name(self, point):
name = self.model().headerData(self.highlightedColumn, Qt.Orientation.Horizontal)
return name

至于从t表中查询a字段,就没什么难度了。

非自定义方法

当然,以上只是展示一种高级用法,只是单纯为了增加工作量的。或者说增加自己的不可替代性

实际上还有一个更简单的方法,那就是QTableViewcurrentIndex属性。这个属性使得用户能够在点击表格中任何一个点的时候返回当前点击的索引。

也就是说,通过这个方法的话完全不需要任何自定义,所有的内容直接写在主窗口逻辑里面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("my_title")
self.setGeometry(0, 0, 1920, 1080)
self.showMaximized()
self.setWindowIcon('my_ico.ico')
self.my_tableView = QTableView()
self.my_tableHeader = QHeaderView()
self.my_model = QStandardModel()
self.my_tableView.setHorizontalHeader(self.my_tableHeader)
self.my_tableView.clicked.connect(self.get_column_name)
def get_column_name(self):
index = self.my_tableView.currentIndex().column()
name = self.my_model.headerData(index, Qt.Orientation.Horizontal)
print(name)

这个方法就简单多了。