QTableWidget是Qt程序中常用的显示数据表格的控件,QTableWidget是QTableView的子类,它使用标准的数据模型。
并且其单元数据是通过QTableWidgetItem对象来实现的,使用QTableWidget时就需要QTableWidgetItem。用来表示表格中的一个单元格,整个表格就是用各个单元格构建起来的。
from PyQt5.Qt import *
import sys
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('QTableWidget-人员信息')
self.resize(600, 600)
self.__setup_ui()
def __setup_ui(self):
self.table_widget = QTableWidget(self)
self.table_widget.setColumnCount(3) # 3列
self.table_widget.setHorizontalHeaderLabels(['姓名', '身高', '体重']) # 表头
self.table_widget.setShowGrid(True) # 显示网格
# self.table_widget.verticalHeader().setVisible(False) # 不显示垂直表头
# 注意:单元格可以设置大小、还可以设置成控件、也可以添加图片,还可以设置右键菜单等灵活的操作模式
# 设置表格为自使用伸缩模式,即可根据窗口大小来改变网格的大小
self.table_widget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
# 也可以单独设置每一列的伸缩样式
# self.table_widget.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeToContents)
# self.table_widget.horizontalHeader().setSectionResizeMode(1, QHeaderView.ResizeToContents)
# self.table_widget.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch)
self.table_widget.setEditTriggers(QAbstractItemView.NoEditTriggers) # 表格禁止编辑
self.table_widget.setRowCount(3) # 不设置行数,内容无法展示
for i in range(3):
name_item = QTableWidgetItem(f'name_{i + 1}')
name_item.setTextAlignment(Qt.AlignLeft) # 创建item并设置内容、对齐方式
height_item = QTableWidgetItem(f'{180 + i}')
height_item.setTextAlignment(Qt.AlignCenter)
weight_item = QTableWidgetItem(f'{60 + i}')
weight_item.setTextAlignment(Qt.AlignRight)
# 单元格设置前景色
if height_item.text() == '180':
height_item.setForeground(QBrush(QColor("#24B64E")))
else:
name_item.setForeground(QBrush(QColor("#f00")))
height_item.setForeground(QBrush(QColor("#f00")))
weight_item.setForeground(QBrush(QColor("#f00")))
# 设置单元格内容
self.table_widget.setItem(i, 0, name_item) # 行/列/内容
self.table_widget.setItem(i, 1, height_item)
self.table_widget.setItem(i, 2, weight_item)
btn = QPushButton('添加一行内容', self)
v_l = QVBoxLayout()
v_l.addWidget(self.table_widget)
v_l.addWidget(btn)
self.setLayout(v_l)
# 信号
self.table_widget.itemChanged.connect(self.__item_change_slot)
self.table_widget.cellPressed.connect(self.table_widget.resizeRowsToContents)
self.table_widget.itemDoubleClicked.connect(self.__item_double_click_slot)
btn.clicked.connect(self.__btn_click)
def __btn_click(self):
current_row = self.table_widget.rowCount()
self.table_widget.setRowCount(current_row + 1)
self.table_widget.setItem(current_row, 0, QTableWidgetItem('new_1'))
self.table_widget.setItem(current_row, 1, QTableWidgetItem('new_2'))
self.table_widget.setItem(current_row, 2, QTableWidgetItem('new_3'))
@staticmethod
def __item_change_slot(item: QTableWidgetItem):
print('itemChanged信号触发:', item)
print(f'item变更的行{item.row()},变更的列{item.column()}')
@staticmethod
def __item_double_click_slot(item: QTableWidgetItem):
if item.column() == 2: # 仅第3列触发
print('您双击了 第{}行,第{}列 的cell'.format(item.row() + 1, item.column() + 1))
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
运行效果图
在通常情况下,一个应用需要和一批数据进行交互,然后以表格的形式输出这些信息,这时就需要用到QTableView类了。
在QTableView中可以使用自定义的数据模型来显示内容,通过setModel来绑定数据源。
QTableWidget继承自QTableView,主要区别是QTableView可以使用自定义的数据模型来显示内容(先通过setModel来绑定数据源)。
而QTableWidget只能使用标准的数据模型,并且其单元格数据是通过QTableWidgetItem对象实现的,通常QTableWidget就能够满足我们的要求。
from PyQt5.Qt import *
import sys
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('QTableView-表格视图控件')
self.resize(600, 600)
# 设置数据层次结构,4行4列
self.model = QStandardItemModel(4, 4)
# 设置水平方向四个头标签文本内容
self.model.setHorizontalHeaderLabels(['标题1', '标题2', '标题3', '标题4'])
# 添加数据
for row in range(4):
for column in range(4):
item = QStandardItem(f'row {row}, column {column}')
# 设置4行4列,每个表格item位置的文本值
self.model.setItem(row, column, item)
# 实例化表格视图,设置模型为自定义的模型
self.table_view = QTableView()
self.table_view.setModel(self.model)
# 将表格填满窗口
# 水平方向标签拓展剩下的窗口部分,填满表格
self.table_view.horizontalHeader().setStretchLastSection(True)
# 水平方向,表格大小拓展到适当的尺寸
self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
# 添加数据
self.model.appendRow([
QStandardItem('11'),
QStandardItem('22'),
QStandardItem('33'),
QStandardItem('44'),
])
# 删除当前所选中的数据(通过btn按钮实现)
self.btn = QPushButton(text='删除', parent=self)
self.btn.clicked.connect(self.on_btn_slot) # type: ignore
v_l = QVBoxLayout()
v_l.addWidget(self.table_view)
v_l.addWidget(self.btn)
self.setLayout(v_l)
def on_btn_slot(self):
""" 删除操作 """
# 第1种方法
indexes = self.table_view.selectionModel().selection().indexes() # 取当前选中的所有行
if len(indexes) > 0:
index = indexes[0] # 取第一行的索引
self.model.removeRows(index.row(), 1)
# 第2种方法
# index = self.table_view.currentIndex()
# print(index.row())
# self.model.removeRow(index.row())
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
运行效果图