目录
0. 前言
1. QTableWidget介绍
2. QTableWidget简单示例
3. QTableWidget中添加其他控件(QComboBox)
4. 进阶版
5. 结束语
0. 前言
PyQt5控件学习之-QTableWidget:主要用于设计一个表格,表格内容中包含了其他控件,并且获取这些控件的值。
1. QTableWidget介绍
QTableWidget是Qt程序中常用的显示数据表格的控件,QTableWidget是QTableView的子类,它使用标准的数据模型,并且其单元数据是通过QTableWidgetItem对象来实现的,使用QTableWidget时就需要QTableWidgetItem。用来表示表格中的一个单元格,整个表格就是用各个单元格构建起来的。
QTableWidget类中的常用方法
方法 | 描述 |
---|---|
setROwCount(int row) | 设置QTableWidget表格控件的行数 |
setColumnCount(int col) | 设置QTableWidget表格控件的列数 |
setHorizontalHeaderLabels() | 设置QTableWidget表格控件的水平标签 |
setVerticalHeaderLabels() | 设置QTableWidget表格控件的垂直标签 |
setItem(int ,int ,QTableWidgetItem) | 在QTableWidget表格控件的每个选项的单元控件内添加控件 |
horizontalHeader() | 获得QTableWidget表格控件的表格头,以便执行隐藏 |
rowCount() | 获得QTableWidget表格控件的行数 |
columnCount() | 获得QTableWidget表格控件的列数 |
setEditTriggers(EditTriggers triggers) | 设置表格是否可以编辑,设置表格的枚举值 |
setSelectionBehavior | 设置表格的选择行为 |
setTextAlignment() | 设置单元格内文本的对齐方式 |
setSpan(int row,int column,int rowSpanCount,int columnSpanCount) | 合并单元格,要改变单元格的第row行,column列,要合并rowSpancount行数和columnSpanCount列数 |
setShowGrid() | 在默认情况下表格的显示是有网格的,可以设置True或False用于是否显示,默认True |
setColumnWidth(int column,int width) | 设置单元格行的宽度 |
setRowHeight(int row,int height) | 设置单元格列的高度 |
编辑规则的枚举值类型
选项 | 值 | 描述 |
---|---|---|
QAbstractItemView.NoEditTriggers0No | 0 | 不能对表格内容进行修改 |
QAbstractItemView.CurrentChanged1Editing | 1 | 任何时候都能对单元格进行修改 |
QAbstractItemView.DoubleClicked2Editing | 2 | 双击单元格 |
QAbstractItemView.SelectedClicked4Editing | 4 | 单击已经选中的内容 |
QAbstractItemView.EditKeyPressed8Editing | 8 | 当修改键按下时修改单元格 |
QAbstractItemView.AnyKeyPressed16Editing | 16 | 按任意键修改单元格 |
QAbstractItemView.AllEditTriggers31Editing | 31 | 包括以上所有条件 |
表格选择行为的枚举值
选项 | 值 | 描述 |
---|---|---|
QAbstractItemView.SelectItems0Selecting | 0 | 选中单个单元格 |
QAbstractItemView.SelectRows1Selecting | 1 | 选中一行 |
QAbstractItemView.SelectColumns2Selecting | 2 | 选中一列 |
单元格文本水平对齐方式
选项 | 描述 |
---|---|
Qt.AlignLeft | 将单元格内的内容沿单元格的左边缘对齐 |
Qt.AlignRight | 将单元格内的内容沿单元格的右边缘对齐 |
Qt.AlignHCenter | 在可用空间中,居中显示在水平方向上 |
Qt.AlignJustify | 将文本在可用空间内对齐,默认从左到右 |
单元格文本垂直对齐方式
选项 | 描述 |
---|---|
Qt.AlignTop | 与顶部对齐 |
Qt.AlignBottom | 与底部对齐 |
Qt.AlignVCenter | 在可用空间中,居中显示在垂直方向上 |
Qt.AlignBaseline | 与基线对齐 |
2. QTableWidget简单示例
下面示例展示了一个简单的表格应用,包括设置表格的行列数目,如何添加数据,如何设置表格内容不可编辑等,代码如下:"""
__Title__ = 'example.py'
__Author__ = 'Administrator'
__Date__ = '2020/11/29'
__Version__ = 'Python 3.7.9'
__Software__ = 'PyCharm'
"""
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class Table(QWidget):
def __init__(self):
super(Table, self).__init__()
self.initUI()
def initUI(self):
self.setWindowTitle("QTableWidget例子")
self.resize(400, 300)
layout = QHBoxLayout()
# 设置一个4行3列的表格
tableWidget = QTableWidget(4, 3)
# 设置标题
tableWidget.setHorizontalHeaderLabels(['姓名', '性别', '体重(kg)'])
# 添加数据
item = QTableWidgetItem('王者荣耀')
# 设置名字不可编辑
item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
tableWidget.setItem(0, 0, item)
item = QTableWidgetItem('男')
tableWidget.setItem(0, 1, item)
item = QTableWidgetItem('170')
tableWidget.setItem(0, 2, item)
# 添加tableWidget到水平布局中
layout.addWidget(tableWidget)
# 应用水平布局
self.setLayout(layout)
if __name__ == '__main__':
app = QApplication(sys.argv)
win = Table()
win.show()
sys.exit(app.exec_())
3. QTableWidget中添加其他控件(QComboBox)
先看一下效果,有兴趣的同学可以先试着搞个这样的,代码在后面展示
为了达到上面的效果,需要在表格中添加一个QComboBox控件,该控件中添加了座位的信息,这里采用页面和逻辑分离的模式,QTableWidget_Test.ui为UI页面文件(通过pyuic转换为QTableWidget_Test.py),main.py为主逻辑文件具体实现如下:
QTableWidget_Test.py
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'QTableWidget_Test.ui'
#
# Created by: PyQt5 UI code generator 5.15.1
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(588, 375)
self.tableWidget = QtWidgets.QTableWidget(Form)
self.tableWidget.setGeometry(QtCore.QRect(0, 0, 591, 381))
# 设置表格行数为7
self.tableWidget.setRowCount(7)
# 设置列数为4
self.tableWidget.setColumnCount(4)
# 设置控件名为tableWidget
self.tableWidget.setObjectName("tableWidget")
self.retranslateUi(Form)
# 信号自动绑定槽函数
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "QTableWidget_Ui"))
main.py
"""
__Title__ = 'main.py'
__Author__ = 'Administrator'
__Date__ = '2020/11/22'
__Version__ = 'Python 3.7.9'
__Software__ = 'PyCharm'
"""
import sys
import random
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QComboBox, QTableWidgetItem
from QTableWidget_Test import Ui_Form
class MyGui(QWidget, Ui_Form):
def __init__(self):
super(MyGui, self).__init__()
self.setupUi(self)
# 水平布局
self.layout = QHBoxLayout()
# 将表格控件添加到水平布局
self.layout.addWidget(self.tableWidget)
# 设置标题
label_list = ['车次', '始发地', '目的地', '座位']
self.tableWidget.setHorizontalHeaderLabels(label_list)
# 定义车次列表
car_list = ['K211', 'D342', 'Z21', 'G1432', 'T211', 'D9540', 'K234']
# 定义始发地和目的地
area_info = ['北京', '上海', '深圳', '广州', '新疆', '武汉', '哈尔滨']
# 定义车次和座位的关系
seat_info = {
'K': ['硬座', '硬卧', '软卧', '无座'],
'T': ['硬座', '硬卧', '软卧', '无座'],
'Z': ['硬座', '硬卧', '软卧', '无座'],
'D': ['二等座', '一等座', '商务座', '无座'],
'G': ['二等座', '一等座', '商务座']
}
# 开始向表格中填充数据
for row in range(len(car_list)):
for column in range(len(label_list)):
# 列为0,填入普通文字
if column == 0:
# 内容
item = QTableWidgetItem(car_list[row])
# 设置此格不可编辑,修改
item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
# 将内容填入位置(row, column)
self.tableWidget.setItem(row, column, item)
elif column == 1 or column == 2:
# 内容
item = QTableWidgetItem(area_info[random.randint(0, len(area_info) - 1)])
# 设置此格不可编辑,修改
item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
# 将内容填入位置(row, column)
self.tableWidget.setItem(row, column, item)
else:
# 下拉选择控件
self.comb = QComboBox()
# 向下拉控件中添加内容
self.comb.addItems(seat_info[car_list[row][0]])
# 为下拉控件添加信号和槽函数
self.comb.currentIndexChanged.connect(self.comb_change)
# 将控件填入位置(row, column)
self.tableWidget.setCellWidget(row, column, self.comb)
# 为表格控件添加信号和槽函数
self.tableWidget.clicked.connect(self.click_position)
# 应用水平布局
self.setLayout(self.layout)
def click_position(self):
"""
表格控件点击信号绑定的槽函数
:return: None
"""
# 当前点击行标
row = self.tableWidget.currentRow()
# 当前点击列标
column = self.tableWidget.currentColumn()
print('当前位置: (%s, %s)' % (row, column))
def comb_change(self):
"""
获取下拉(comb)控件的值
:return: None
"""
# 当前点击行标
row = self.tableWidget.currentRow()
# 当前点击列标
column = self.tableWidget.currentColumn()
# self.sender():发送信号的控件
print('row:{}, column: {}, seat: {}'.format(row, column, self.sender().currentText()))
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MyGui()
win.show()
sys.exit(app.exec_())
4. 进阶版
在上一步实现的基础上,又有一个新的需求,在每一行前面添加一个点击按钮,当按钮选中时,QCombBox控件才可以选择座位,各个按钮是互斥的(只能有一个被选中),效果如下:
这里ui文件保持不变, 实现的主逻辑代码如下:
main_upload.py
"""
__Title__ = 'main.py'
__Author__ = 'Administrator'
__Date__ = '2020/11/22'
__Version__ = 'Python 3.7.9'
__Software__ = 'PyCharm'
"""
import sys
import random
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QComboBox, \
QTableWidgetItem, QRadioButton, QHeaderView, QButtonGroup, QVBoxLayout, QAbstractItemView
from QTableWidget_Test import Ui_Form
class MyGui(QWidget, Ui_Form):
def __init__(self):
super(MyGui, self).__init__()
self.setupUi(self)
# 全局水平布局
self.layout = QHBoxLayout()
# 增加一个按钮组
self.group = QButtonGroup()
# 设置按钮组内的按钮互斥(只能一个被选中)
self.group.setExclusive(True)
# 设置标题
label_list = ['', '车次', '始发地', '目的地', '座位']
self.tableWidget.setHorizontalHeaderLabels(label_list)
# 表格头随控件变化(水平方向占满窗体)
self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
# 隐藏列表头(垂直方向的数字表[0, 1, 2...])
self.tableWidget.verticalHeader().setVisible(False)
# 设置表格内容不可编辑
self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
# 设置数据按车次字母排序(排序需要放在前面,放在后面会乱掉)
self.tableWidget.sortItems(1, Qt.AscendingOrder)
# 定义车次列表
car_list = ['K211', 'D342', 'Z21', 'G1432', 'T211', 'D9540', 'K234']
# 定义始发地和目的地
area_info = ['北京', '上海', '深圳', '广州', '新疆', '武汉', '哈尔滨',
'重庆', '海南', '南昌', '西安', '南京', '合肥', '福州']
# 定义车次和座位的关系
seat_info = {
'K': ['硬座', '硬卧', '软卧', '无座'],
'T': ['硬座', '硬卧', '软卧', '无座'],
'Z': ['硬座', '硬卧', '软卧', '无座'],
'D': ['二等座', '一等座', '商务座', '无座'],
'G': ['二等座', '一等座', '商务座']
}
# 开始向表格中填充数据
for row in range(len(car_list)):
for column in range(len(label_list)):
# 列为0,填入radiobutton控件
if column == 0:
# 添加radiobutton控件
self.radio = QRadioButton()
# radio控件加入按钮组,后续遍历使用
self.group.addButton(self.radio)
# 绑定槽函数
self.radio.clicked.connect(self.radio_check)
# 添加垂直布局,为了使radio控件可以居中
v = QVBoxLayout()
# radio控件添加进垂直布局
v.addWidget(self.radio)
# 设置垂直布局中的控件居中
v.setAlignment(Qt.AlignCenter)
# 新增窗体应用垂直布局
w = QWidget()
# 窗体应用布局
w.setLayout(v)
# 将控件填入位置(row, column)
self.tableWidget.setCellWidget(row, column, w)
# 列为1,填入车次
elif column == 1:
# 内容
item = QTableWidgetItem(car_list[row])
# 设置此格不可编辑,修改(上面定义了全局的,这里可以注释)
# item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
# 将内容填入位置(row, column)
self.tableWidget.setItem(row, column, item)
# 列为2或3,填入始发站或目的地
elif column == 2 or column == 3:
# 内容
item = QTableWidgetItem(area_info[random.randint(0, len(area_info) - 1)])
# 设置此格不可编辑,修改(上面定义了全局的,这里可以注释)
# item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
# 将内容填入位置(row, column)
self.tableWidget.setItem(row, column, item)
# 列为4,填入QCombBox控件
else:
# 下拉选择控件
self.comb = QComboBox()
# 向下拉控件中添加内容
self.comb.addItems(seat_info[car_list[row][0]])
# 设置QComboBox控件不可用
self.comb.setEnabled(False)
# 设置背景色(代表不可用)
self.comb.setStyleSheet("background-color: rgb(198, 199, 206)")
# 为下拉控件添加信号和槽函数
self.comb.currentIndexChanged.connect(self.comb_change)
# 将控件填入表格
self.tableWidget.setCellWidget(row, column, self.comb)
# 为表格控件添加信号和槽函数
self.tableWidget.itemClicked.connect(self.click_position)
# 将表格控件添加到水平布局
self.layout.addWidget(self.tableWidget)
# 应用水平布局
self.setLayout(self.layout)
def radio_check(self):
"""
radio按钮被点击是触发
:return: None
"""
# 遍历按钮组中的按钮
for index, button in enumerate(self.group.buttons()):
# 判断所有按钮状态
if button.isChecked():
# 被选中的按钮将该行的座位列控件QComBox改为可用
self.tableWidget.cellWidget(index, 4).setEnabled(True)
# 设置背景色(代表可用)
self.tableWidget.cellWidget(index, 4).setStyleSheet("background-color: rgb(255, 255, 255)")
# 获取默认的座位值
print('当前默认座位: %s' % (self.tableWidget.cellWidget(index, 4).currentText()))
else:
# 未被选中的按钮将该行的座位列控件QComBox改为不可用
self.tableWidget.cellWidget(index, 4).setEnabled(False)
# 设置背景色(代表不可用)
self.tableWidget.cellWidget(index, 4).setStyleSheet("background-color: rgb(198, 199, 206)")
def click_position(self, item):
"""
表格控件点击信号绑定的槽函数
:param item: 点击表格传过来的数据
:return: None
"""
# 当前点击行标
row = self.tableWidget.currentRow()
# 当前点击列标
column = self.tableWidget.currentColumn()
print('当前位置: row: %s, columns: %s, 内容: %s' % (row, column, item.text()))
def comb_change(self):
"""
获取下拉(comb)控件的值
:return: None
"""
# 当前点击行标
row = self.tableWidget.currentRow()
# 当前点击列标
column = self.tableWidget.currentColumn()
# self.sender():发送信号的控件
print('当前位置: row: %s, columns: %s, 内容: %s' % (row, column, self.sender().currentText()))
if __name__ == '__main__':
app = QApplication(sys.argv)
# 创建窗体
win = MyGui()
# 展示窗体
win.show()
sys.exit(app.exec_())
代码注解:
1、表格内容不可编辑
方式一: 通过tableWidget设置全局(推荐使用)self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
方式二: 修改Item为不可编辑,再填入单元格(这种方式点击控件所在格时也会打印坐标位置)
item = QTableWidgetItem(car_list[row]) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
2、表格头随控件变化(水平方向占满窗体)
self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
3、隐藏列表头(垂直方向的数字表[0, 1, 2…])
self.tableWidget.verticalHeader().setVisible(False)
4、设置数据按车次字母排序(排序需要放在表格创建时前面,放在后面会乱掉,如下所示)
self.tableWidget.sortItems(1, Qt.AscendingOrder)
5、单元格内控件居中
self.radio = QRadioButton() #需要添加到单元格的控件
v = QVBoxLayout() #垂直布局(因为单元格内只添加一个控件,所以水平、垂直布局都可以)
v.addWidget(self.radio) #向局部布局中添加控件
v.setAlignment(Qt.AlignCenter) #设置布局中的所有控件居中(水平、垂直)显示
w = QWidget() #新建一个空白控件
w.setLayout(v) #上面已经添加radio控件的垂直布局放入空白控件中
self.tableWidget.setCellWidget(row, column, w) #将上一步的控件填入单元格
6、点击radio控件,如何获取到同一行的QCombBox控件?
self.tableWidget.cellWidget(index, 4) #获取控件
5. 结束语
本文只是记录了基本的用法和自己想到的某个场景的实现,更多的功能或者你自己想实现的需求,可以依葫芦画瓢来实现。看到这里,各位看官忍心不给个关注和点赞么!本文涉及代码:点击下载本文涉及代码
参考:
1、pyqt5中的tableWidget添加checkBox、comboBox
2、PyQt5 单元格里添加控件
3、PyQt5 - Table Widget初始化+内容防止编辑
4、PyQt5高级界面控件之QTableWidget