TableWidget和TableView区别:
PyQt6提供了两种表格控件,分别是TableWidget和TableView,其中,TableView是基于模型的,它是TableWidget的父类,使用TableView时,首先需要建立模型,然后再保存数据;而TableWidget是TableView的升级版本,它已经内置了一个数据存储模型QTableWidgetItem,我们在使用时,不必自己建立模型,而直接使用setItem()方法即可添加数据。所以在实际开发时,推荐使用TableWidget控件作为表格。
一、要实现列表先附效果:

拖拽Table widget参数名为 tableWidget

小案例代码:
from PySide6.QtWidgets import (QApplication, QTableWidget,QTableWidgetItem,QAbstractItemView,QHeaderView)
from PySide6.QtUiTools import QUiLoader
import sys
class Window:
def __init__(self):
# 加载 UI 文件
self.ui = QUiLoader().load('ui/dy.ui')
self.ui.setWindowTitle('测试')
# 获取 QTableWidget
table: QTableWidget = self.ui.tableWidget
table.setRowCount(2)
table.setColumnCount(6)
table.setHorizontalHeaderLabels(['编号', '书名', '类别', '作者', '出版日期', '价格'])
table.setItem(0, 0, QTableWidgetItem('1'))
table.setItem(0, 1, QTableWidgetItem('Python程序设计'))
table.setItem(0, 2, QTableWidgetItem('计算机'))
table.setItem(0, 3, QTableWidgetItem('张三'))
table.setItem(0, 4, QTableWidgetItem('2021-10-10'))
table.setItem(0, 5, QTableWidgetItem('20.00'))
table.setItem(1, 0, QTableWidgetItem('2'))
table.setItem(1, 1, QTableWidgetItem('Python程序设计'))
table.setItem(1, 2, QTableWidgetItem('计算机'))
table.setItem(1, 3, QTableWidgetItem('张三'))
table.setItem(1, 4, QTableWidgetItem('2021-10-10'))
table.setItem(1, 5, QTableWidgetItem('20.00'))
# table.resizeColumnsToContents() # 设置列宽跟随内容改变
table.verticalHeader().setVisible(False) # 隐藏垂直标题 序号
# 设置最后一列自动填充容器
# table.horizontalHeader().setStretchLastSection(True)
# 设置列宽模式:所有列均匀拉伸填满表格
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
# 禁止编辑单元格
table.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers)
# ---------------------
# 程序入口
# ---------------------
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
window.ui.show()
sys.exit(app.exec())
二、要实现列表全选和取消全选先附效果:


新增全选按钮,名称为:selectAllButton

小案例代码:
from PySide6.QtWidgets import (QApplication,
QTableWidget,
QTableWidgetItem,
QAbstractItemView,
QHeaderView,
QCheckBox,
QWidget,
QHBoxLayout)
from PySide6.QtUiTools import QUiLoader
from PySide6.QtCore import Qt
import sys
class Window:
def __init__(self):
# 加载 UI 文件
self.ui = QUiLoader().load('ui/dy.ui')
self.ui.setWindowTitle('测试')
self.ui.executeButton.clicked.connect(self.executeButton)
# 连接按钮点击事件
self.ui.selectAllButton.clicked.connect(self.toggle_select_all)
# 获取 QTableWidget
table: QTableWidget = self.ui.tableWidget
table.setRowCount(2)
table.setColumnCount(6)
table.setHorizontalHeaderLabels(['', '书名', '类别', '作者', '出版日期', '价格'])
# table.resizeColumnsToContents() # 设置列宽跟随内容改变
table.verticalHeader().setVisible(False) # 隐藏垂直标题 序号
# 设置最后一列自动填充容器
# table.horizontalHeader().setStretchLastSection(True)
# 设置列宽模式:所有列均匀拉伸填满表格
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
# 禁止编辑单元格
table.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers)
# 存储复选框对象(可选:用于后续操作)
self.checkboxes = []
# 为每一行创建带复选框的单元格
for row in range(2):
# 创建复选框并居中
checkbox = QCheckBox()
checkbox.setChecked(True) # 默认选中,可按需设置
checkbox.stateChanged.connect(lambda state, r=row: self.on_checkbox_state_changed(r, state))
# 创建一个居中的 widget 容器
container = QWidget()
layout = QHBoxLayout(container)
layout.addWidget(checkbox)
layout.setAlignment(Qt.AlignCenter)
layout.setContentsMargins(0, 0, 0, 0)
# 将容器设为单元格 widget
table.setCellWidget(row, 0, container)
# 保存复选框引用(可选)
self.checkboxes.append(checkbox)
# 其他列填充数据(从第1列开始)
table.setItem(row, 1, QTableWidgetItem('Python程序设计'))
table.setItem(row, 2, QTableWidgetItem('计算机'))
table.setItem(row, 3, QTableWidgetItem('张三'))
table.setItem(row, 4, QTableWidgetItem('2021-10-10'))
table.setItem(row, 5, QTableWidgetItem('20.00'))
def toggle_select_all(self):
"""全选 / 取消全选"""
# 判断当前状态:是否全部已选中
all_selected = all(cb.isChecked() for cb in self.checkboxes)
# 如果当前是全选状态,则取消全选;否则全选
new_state = False if all_selected else True
for cb in self.checkboxes:
cb.setChecked(new_state)
self.update_select_all_button_text()
print("批量操作:", "全选" if new_state else "取消全选")
def update_select_all_button_text(self):
"""更新按钮文字"""
all_selected = all(cb.isChecked() for cb in self.checkboxes)
text = "取消全选" if all_selected else "全选"
self.ui.selectAllButton.setText(text)
def on_checkbox_state_changed(self, row, state):
"""行复选框状态改变"""
if state == Qt.Checked:
print(f"第 {row + 1} 行被选中")
else:
print(f"第 {row + 1} 行被取消选中")
def get_selected_rows(self):
"""获取选中的行"""
return [i for i, cb in enumerate(self.checkboxes) if cb.isChecked()]
def executeButton(self):
"""示例:执行按钮点击"""
selected = self.get_selected_rows()
print("当前选中的行:", selected)
# ---------------------
# 程序入口
# ---------------------
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
window.ui.show()
sys.exit(app.exec())
二、要实现列表全选选中Excel导出功能先附效果:

新增全选按钮,名称为:exportButton

小案例代码:
from PySide6.QtWidgets import (QApplication,
QTableWidget,
QTableWidgetItem,
QAbstractItemView,
QHeaderView,
QCheckBox,
QWidget,
QHBoxLayout)
from PySide6.QtUiTools import QUiLoader
from PySide6.QtWidgets import QFileDialog # 添加导入
import openpyxl
from openpyxl.styles import Alignment, Font
from PySide6.QtCore import Qt
import sys
class Window:
def __init__(self):
# 加载 UI 文件
self.ui = QUiLoader().load('ui/dy.ui')
self.ui.setWindowTitle('测试')
# Excel 导出按钮
self.ui.exportButton.clicked.connect(self.exportButton)
# 全选 / 取消全选按钮
self.ui.selectAllButton.clicked.connect(self.toggle_select_all)
# 获取 QTableWidget
table: QTableWidget = self.ui.tableWidget
table.setRowCount(2)
table.setColumnCount(6)
table.setHorizontalHeaderLabels(['', '书名', '类别', '作者', '出版日期', '价格'])
# table.resizeColumnsToContents() # 设置列宽跟随内容改变
table.verticalHeader().setVisible(False) # 隐藏垂直标题 序号
# 设置最后一列自动填充容器
# table.horizontalHeader().setStretchLastSection(True)
# 设置列宽模式:所有列均匀拉伸填满表格
# table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
# 设置列宽策略
table.horizontalHeader().setSectionResizeMode(0, QHeaderView.Fixed)
table.horizontalHeader().resizeSection(0, 70) # 复选框列宽度
# 其他列等比例拉伸
for col in range(1, 6):
table.horizontalHeader().setSectionResizeMode(col, QHeaderView.Stretch)
# table.resizeColumnsToContents() # 设置列宽跟随内容改变
# 禁止编辑单元格
table.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers)
# 存储复选框对象(可选:用于后续操作)
self.checkboxes = []
# 为每一行创建带复选框的单元格
for row in range(2):
# 创建复选框并居中
checkbox = QCheckBox()
checkbox.setChecked(False) # 默认未选中,可按需设置
checkbox.stateChanged.connect(lambda state, r=row: self.on_checkbox_state_changed(r, state))
# 创建一个居中的 widget 容器
container = QWidget()
layout = QHBoxLayout(container)
layout.addWidget(checkbox)
layout.setAlignment(Qt.AlignCenter)
layout.setContentsMargins(0, 0, 0, 0)
# 将容器设为单元格 widget
table.setCellWidget(row, 0, container)
# 保存复选框引用(可选)
self.checkboxes.append(checkbox)
# 其他列填充数据(从第1列开始)
table.setItem(row, 1, QTableWidgetItem('Python程序设计'))
table.setItem(row, 2, QTableWidgetItem('计算机'))
table.setItem(row, 3, QTableWidgetItem('张三'))
table.setItem(row, 4, QTableWidgetItem('2021-10-10'))
table.setItem(row, 5, QTableWidgetItem('20.00'))
def toggle_select_all(self):
"""全选 / 取消全选"""
# 判断当前状态:是否全部已选中
all_selected = all(cb.isChecked() for cb in self.checkboxes)
# 如果当前是全选状态,则取消全选;否则全选
new_state = False if all_selected else True
for cb in self.checkboxes:
cb.setChecked(new_state)
self.update_select_all_button_text()
print("批量操作:", "全选" if new_state else "取消全选")
def update_select_all_button_text(self):
"""更新按钮文字"""
all_selected = all(cb.isChecked() for cb in self.checkboxes)
text = "取消全选" if all_selected else "全选"
self.ui.selectAllButton.setText(text)
def on_checkbox_state_changed(self, row, state):
"""行复选框状态改变"""
if state == Qt.Checked:
print(f"第 {row + 1} 行被选中")
else:
print(f"第 {row + 1} 行被取消选中")
def get_selected_rows(self):
"""获取选中的行"""
return [i for i, cb in enumerate(self.checkboxes) if cb.isChecked()]
def exportButton(self):
"""导出选中的行到 Excel 文件"""
selected_rows = self.get_selected_rows()
if not selected_rows:
print("没有选中任何行,无需导出。")
return
# 弹出保存文件对话框
file_path, _ = QFileDialog.getSaveFileName(
self.ui,
"保存 Excel 文件",
"导出数据.xlsx", # 默认文件名
"Excel 文件 (*.xlsx)"
)
if not file_path:
return # 用户取消
# 获取表头
headers = ['序号', '书名', '类别', '作者', '出版日期', '价格']
# 准备数据(带上序号)
data = []
for idx, row in enumerate(selected_rows, start=1):
row_data = [
idx,
self.ui.tableWidget.item(row, 1).text(),
self.ui.tableWidget.item(row, 2).text(),
self.ui.tableWidget.item(row, 3).text(),
self.ui.tableWidget.item(row, 4).text(),
self.ui.tableWidget.item(row, 5).text()
]
data.append(row_data)
# 创建 Excel 工作簿
wb = openpyxl.Workbook()
ws = wb.active
ws.title = "导出数据"
# 写入表头
ws.append(headers)
# 设置表头样式
header_font = Font(bold=True)
alignment = Alignment(horizontal='center', vertical='center')
for cell in ws[1]:
cell.font = header_font
cell.alignment = alignment
# 写入数据
for row_data in data:
ws.append(row_data)
# 设置所有单元格居中
for row in ws.iter_rows(min_row=1, max_row=ws.max_row, max_col=6):
for cell in row:
cell.alignment = alignment
# 自动调整列宽
column_widths = [5, 15, 10, 10, 12, 8] # 序号、书名、类别、作者、日期、价格
for i, width in enumerate(column_widths, start=1):
ws.column_dimensions[openpyxl.utils.get_column_letter(i)].width = width
# 保存文件
try:
wb.save(file_path)
print(f"✅ 数据已成功导出到:{file_path}")
except Exception as e:
print(f"❌ 导出失败:{e}")
# ---------------------
# 程序入口
# ---------------------
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
window.ui.show()
sys.exit(app.exec())
491

被折叠的 条评论
为什么被折叠?



