2024-06-14-Pyside6数据存储
1.基于项的控件
1.1 基于项的控件
PySide6 有专门的显示数据的控件和存储数据的模型,可以显示和存储不同形式的数据。
显示数据的控件分为两类,一类是基于 项(item)的控件,另一类是基于 模型(model)的控件,基于项的控件是基于模型的控件的简便类。基于项的控件把读取到的数据存储到项中,基于模型的控件把数据存储到模型中,或通过模型提供读取数据的接口,然后通过控件把数据模型中的数据或关联的数据显示出来。
基于项的控件有 列表控件 QListWidget
、表格控件 QTableWidget
和 树结构控件 QTreeWidget
,它们是从基于模型的控件继承而来的,基于模型的控件有 QListView
、QTableView
和 QTreeView
,这些控件之间的继承关系如下所示。
QAbstractItemView 类的常用方法:
# 实例方法
setModel(model:QAbstractItemModel) -> None # 设置数据模型
setSelectionModel(selectionModel:QItemSelectionModel) -> None # 设置选择模型
setAlternatingRowColors(enable:bool) -> None # 设置交替色
# 槽方法
clearSelection() -> None # 清空选择
1.2 列表控件及其项
列表控件 QListWidget 由一列多行构成,每行称为一个项(item),每个项是一个 QListWidgetItem 对象。可以继承 QListWidgetItem 创建用户自定义的项,也可以先创建 QWidget 实例,在其上添加一些控件,然后把 QWidget 放到 QListWidgetItem 的位置,形成复杂的列表控件。
列表控件 QListWidget 是从 QListView 类继承而来的,用 QListWidget 类创建列表控件的方法如下所示:
QListWidget(parent:QWidget=None)
其中 parent 是 QListWidget 列表控件所在的父窗口或控件。
用 QListWidgetItem 创建列表项的方法如下所示:
QListWidgetItem(listview:QListWidget=None, type:int=QListWidgetItem.Type)
QListWidgetItem(text:str, listview:QListWidget=None, type:int=QListWidgetItem.Type)
QListWidgetItem(icon:Union[QIcon, QPixmap], text:str, listview:QListWidget=None, type:int=QListWidgetItem.Type)
其中 type 可取 QListWidgetItem.Type(值为 0)或 QListWidgetItem.UserType(值为 1000),前者是默认值,后者是用户自定义类型的最小值。可以用 QListWidgetItem 类创建子类,定义新的类型。
列表控件 QListWidget 的常用方法如下:
# 实例方法
addItem(item:QListWidgetItem) -> None # 在列表控件中添加项
addItem(label:str) -> None # 用文本创建并添加项
addItems(labels:Sequence[str]) -> None # 用文本列表创建添加多个项
insertItem(row:int, item:QListWidgetItem) -> None # 在列表控件中插入项
insertItem(row:int, label:str) -> None # 用文本创建项并插入项
insertItems(row:int, labels:Sequence[str]) -> None # 用文本列表创建项并插入多个项
setCurrentItem(item:QListWidgetItem) -> None # 设置当前项
currentItem() -> QListWidgetItem # 返回当前项
setCurrentRow(row:int) -> None # 指定第row行为当前行
currentRow() -> int # 返回当前行
selectedItems() -> List[QListWidgetItem] # 返回选择项的列表
row(item:QListWidgetItem) -> int # 返回当前项的行号
item(row:int) -> QListWidgetItem # 返回指定行的项
itemAt(p:QPoint) -> QListWidgetItem # 返回指定位置的项
itemAt(x:int, y:int) -> QListWidgetItem # 返回指定位置的项
itemFromIndex(index:QModelIndex) -> QListWidgetItem # 返回指定索引的项
visualItemRect(item:QListWidgetItem) -> QRect # 返回指定项的矩形
setItemWidget(item:QListWidgetItem, widget:QWidget) -> None # 把某控件显示在指定项的位置处
itemWidget(item:QListWidgetItem) -> QWidget # 返回指定项位置处的控件
removeItemWidget(item:QListWidgetItem) -> None # 删除指定项位置处的控件
openPersistentEditor(item:QListWidgetItem) -> None # 打开指定项的编辑框,用于编辑文本
isPersistentEditorOpen(item:QListWidgetItem) -> bool # 返回指定项的编辑框是否打开
closePersistentEditor(item:QListWidgetItem) -> None # 关闭指定项的编辑框
count() -> int # 返回项的数量
takeItem(row:int) -> QListWidgetItem # 从列表控件中删除并返回项
findItems(text:str, flags:Qt.MatchFlags) -> List[QListWidgetItem] # 返回匹配项的列表
setSortingEnabled(enable:bool) -> None # 设置列表控件是否可以排序
isSortingEnabled() -> bool # 返回列表控件是否可以排序
sortItems(order:Qt.SortOrder=Qt.AscendingOrder) -> None # 按照排序方式进行项的排序
supportedDropActions() -> Qt.DropActions # 返回列表控件支持的拖动和粘贴操作
mimeData(items:Sequence[QListWidgetItem]) -> QMimeData # 获取多个项的mime数据QMimeData
mimeTypes() -> List[str] # 返回mime数据的类型列表
# 槽方法
clear() -> None # 清空列表控件
scrollToItem(item:QListWidgetItem, hint=QAbstractItemView.ScrollHint.EnsureVisible) -> None # 滚动到指定项,使其可见
用 setSortingEnabled(bool)
方法设置是否可以进行排序;用 sortItems(order=Qt.AscendingOrder)
方法设置排序方法,其中 order 可取值如下:
Qt.AscendingOrder.AscendingOrder # 升序
Qt.AscendingOrder.DescendingOrder # 降序
用 findItems(text:str,flags:Qt.MatchFlags)
方法可以查找满足匹配规则的项 List[QListWidgetItem],其中参数 flags 可取值如下:
Qt.MatchFlags.MatchExactly
Qt.MatchFlags.MatchFixedString
Qt.MatchFlags.MatchContains
Qt.MatchFlags.MatchStartsWith
Qt.MatchFlags.MatchEndsWith
Qt.MatchFlags.MatchCaseSensitive
Qt.MatchFlags.MatchRegularExpression
Qt.MatchFlags.MatchWildcard
Qt.MatchFlags.MatchWrap
Qt.MatchFlags.MatchRecursive
用 supportedDropActions()
方法获取支持的拖放动作 Qt.DropAction,其中 Qt.DropAction 可以取值如下:
Qt.DropAction.CopyAction # 复制
Qt.DropAction.MoveAction # 移动
Qt.DropAction.LinkAction # 链接
Qt.DropAction.IgnoreAction # 什么都不做
Qt.DropAction.TargetMoveAction # 目标对象接管
列表控件 QListWidget 的常用信号如下:
currentItemChanged(current:QListWidgetItem, previous:QListWidgetItem) # 当前项发生改变时发射信号
currentRowChanged(currentRow:int) # 当前行发生改变时发射信号
currentTextChanged(currentText:str) # 当前项的文本发生改变时发射信号
itemActivated(item:QListWidgetItem) # 单击或双击项,使其变成活跃项时发射信号
itemChanged(item:QListWidgetItem) # 项的数据发生改变时发射信号
itemClicked(item:QListWidgetItem) # 单击项时发射信号
itemDoubleClicked(item:QListWidgetItem) # 双击项时发射信号
itemEntered(item:QListWidgetItem) # 光标进入某个项时发射信号
itemPressed(item:QListWidgetItem) # 当鼠标在某个项按下时发射信号
itemSelectionChanged() # 项的选择状态发生改变时发射信号
列表项 QListWidgetItem 的常用方法如下:
setText(text:str) -> None # 设置文字
text() -> str # 获取文字
setTextAlignment(alignment:Qt.Alignment) -> None # 设置文字对齐方式
setIcon(icon:QIcon) -> None # 设置图标
icon() -> QIcon # 获取图标
setToolTip(toolTip:str) -> None # 设置提示文字
setFont(font:QFont) -> None # 设置字体
setForeground(brush:QColor) -> None # 设置前景色
setBackground(brush:QColor) -> None # 设置背景色
setStatusTip(statusTip:str) -> None # 设置状态提示文字,需激活mouseTracking属性
setWhatsThis(whatsThis:str) -> None # 设置按Shift+F1键的显示文字
setCheckState(state:Qt.CheckState) -> None # 设置勾选状态
checkState() -> Qt.CheckState # 获取勾选状态
setFlags(flags:Qt.ItemFlag) -> None # 设置标识
setHidden(hide:bool) -> None # 设置是否隐藏
isHidden() -> bool # 获取是否隐藏
setSelected(select:bool) -> None # 设置是否选中
isSelected() -> bool # 获取是否选中
clone() -> QListWidgetItem # 克隆一个项
listWidget() -> QListWidget # 获取列表视图
write(out:QDataStream) -> None # 将项写入数据流
read(in:QDataStream) -> None # 从数据流中读取项
setData(role:int, value:Any) -> None # 设置某角色的数据
data(role:int) -> Any # 获取某角色的数据
用 setForeground(QColor)
方法和 setBackground(QColor)
方法可以设置前景色和背景色,其中参数 QColor 可以取QBrush、Qt.BrushStyle、Qt.GlobalColor、QGradient、QImage 或 QPixmap。
用 setCheckState(Qt.CheckState)
方法设置项是否处于勾选状态,其中参数 Qt.CheckState 可以取值如下:
Qt.CheckState.Unchecked # 未勾选
Qt.CheckState.PartiallyChecked # 部分勾选,如果有子项
Qt.CheckState.Checked # 勾选
用 setFlags(Qt.ItemFlags)
方法设置项的标识,其中参数 Qt.ItemFlags 可取的值如下所示。
Qt.ItemFlag.NoItemFlags # 没有标识符
Qt.ItemFlag.ItemIsSelectable # 项可选
Qt.ItemFlag.ItemIsEditable # 项可编辑
Qt.ItemFlag.ItemIsDragEnabled # 项可以拖拽
Qt.ItemFlag.ItemIsDropEnabled # 项可以拖放
Qt.ItemFlag.ItemIsUserCheckable # 项可以勾选
Qt.ItemFlag.ItemIsEnabled # 项被激活
Qt.ItemFlag.ItemIsAutoTristate # 如有子项,则有第三种状态
Qt.ItemFlag.ItemNeverHasChildren # 项没有子项
Qt.ItemFlag.ItemIsUserTristate # 可在三种状态之际爱你循环切换
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtWidgets import QListWidget
class MyWidget(QWidget):
def __init__(self):
# 1.调用父类Qwidget类的__init__()方法
super().__init__()
# 2.调用setupUi()方法初始化页面
self.setup_ui()
def setup_ui(self):
# 1.设置窗口对象大小
self.resize(700, 500)
# 2.创建列表控件对象
listWidget = QListWidget(self)
listWidget.resize(300, 100)
# 3.向列表控件中添加值
listWidget.addItem("木之本樱")
listWidget.addItems(["御坂美琴", "夏娜", "赤瞳", "黑瞳"])
# 4.向指定索引处插入值
listWidget.insertItem(3, "涂山苏苏")
listWidget.insertItems(3, ["白钰袖", "风铃儿"])
# 5.获取指定项
item = listWidget.item(1)
# 6.设置指定项的提示信息
item.setToolTip("超电磁炮")
# 7.设置当前选择项
listWidget.setCurrentItem(item)
# 8.设置选择模式
listWidget.setSelectionMode(QListWidget.SelectionMode.ExtendedSelection)
# 9.设置选择项的方式
listWidget.setSelectionBehavior(QListWidget.SelectionBehavior.SelectItems)
# 10.设置显示模式
listWidget.setViewMode(QListWidget.ViewMode.IconMode)
# 11.设置是否自动换行
listWidget.setWordWrap(True)
# 12.定义信号与槽的连接
listWidget.currentItemChanged.connect(self.currentItemChanged)
listWidget.currentTextChanged.connect(self.currentTextChanged)
listWidget.itemActivated.connect(self.itemActivated)
listWidget.itemClicked.connect(self.itemClicked)
listWidget.itemDoubleClicked.connect(self.itemDoubleClicked)
listWidget.itemEntered.connect(self.itemEntered)
listWidget.itemPressed.connect(self.itemPressed)
def currentItemChanged(self, current, previous):
print(f"当前项被改变了,从【{previous.text()}】变成了【{current.text()}】")
def currentTextChanged(self, text):
print("当前项的文本被编辑了,编辑后的文本为:", text)
def itemActivated(self, item):
print(f"【{item.text()}】项被激活了")
def itemClicked(self, item):
print(f"【{item.text()}】项被单击了")
def itemDoubleClicked(self, item):
print(f"【{item.text()}】项被双击了")
def itemEntered(self, item):
print(f"鼠标移入【{item.text()}】项")
def itemPressed(self, item):
print(f"【{item.text()}】项被按下了")
if __name__ == "__main__":
# 1.创建一个QApplication类的实例
app = QApplication(sys.argv)
# 2.创建一个窗口
window = MyWidget()
# 3.展示窗口
window.show()
# 4.进入程序的主循环并通过exit()函数确保主循环安全结束
sys.exit(app.exec())
1.3 表格控件及其项
表格控件 QTableWidget 是从 QTableView 类继承而来的,由多行多列构成,并且含有行表头和列表头,表格控件的每个单元格称为一个项(item),每个项是一个 QTableWidgetItem 对象,可以设置每个项的文本、图标、颜色、前景色和背景色等属性。
用 QTableWidget 类创建表格控件的方法如下所示:
QTableWidget(parent:QWidget=None)
QTableWidget(rows:int, columns:int, parent:QWidget=None)
其中 parent 是表格控件 QTableWidget 所在的父窗口或控件, rows 和 columns 分别指定表格对象的行和列的数量。
用 QTableWidgetItem 创建表格项的方法如下所示:
QTableWidgetItem(type=QTableWidgetItem.Type)
QTableWidgetItem(text:str, type=QTableWidgetItem.Type)
QTableWidgetItem(icon:QIcon, text:str, type=QTableWidgetItem.Type)
其中 type 可取 QTableWidgetItem.Type(值为 0)或 QTableWidgetItem.UserType(值为 1000),前者是默认值,后者是用户自定义类型的最小值。可以用 QTableWidgetItem 类创建子类,定义新表格项。
QTableWidget 类常用方法如下:
# 实例方法
setRowCount(rows:int) -> None # 设置行数
rowCount() -> int # 获取行数
setColumnCount(columns:int) -> None # 设置列数
columnCount() -> int # 获取列数
setItem(row:int, column:int, item:QTableWidgetItem) -> None # 在指定行和列处设置表格项
takeItem(row:int, column:int) -> QTableWidgetItem # 移除并返回指定表格项
setCurrentCell(row:int, column:int) -> None # 设置当前单元格
setCurrentItem(item:QTableWidgetItem) -> None # 设置当前的表格项
currentItem() -> QTableWidgetItem # 返回当前的表格项
currentRow() -> int # 返回当前行号
currentColumn() -> int # 返回当前列号
row(item:QTableWidgetItem) -> int # 返回指定表格项的行号
column(item:QTableWidgetItem) -> int # 返回指定表格项的列号
setHorizontalHeaderItem(column:int, item:QTableWidgetItem) -> None # 设置水平表头
setHorizontalHeaderLabels(labels:Sequence[str]) -> None # 用字符串序列设置水平表头
horizontalHeaderItem(column:int) -> QTableWidgetItem # 获取水平表头的表格项
takeHorizontalHeaderItem(column:int) -> QTableWidgetItem # 移除并返回水平表头的表格项
setVerticalHeaderItem(row:int, item:QTableWidgetItem) -> None # 设置垂直表头
setVerticalHeaderLabels(labels:Sequence[str]) -> None # 用字符串序列设置垂直表头
verticalHeaderItem(row:int) -> QTableWidgetItem # 获取垂直表头的表格项
takeVerticalHeaderItem(row:int) -> QTableWidgetItem # 移除并返回垂直表头的表格项
editItem(item:QTableWidgetItem) -> None # 编辑表格项
findItems(text:str, flags:Qt.MatchFlg) -> List[QTableWidgetItem] # 获取满足条件的表格项列表
item(row:int, column:int) -> QTableWidgetItem # 获取指定行和列处的表格项
itemAt(p:QPoint) -> QTableWidgetItem # 获取指定位置处的表格项
itemAt(x:int, y:int) -> QTableWidgetItem # 获取指定位置处的表格项
openPersistentEditor(item:QTableWidgetItem) -> None # 打开指定项的编辑框,用于编辑文本
isPersistentEditorOpen(item:QTableWidgetItem) -> bool # 返回指定项的编辑框是否打开
closePersistentEditor(item:QTableWidgetItem) -> None # 关闭指定项的编辑框
selectedItems() -> List[QTableWidgetItem] # 返回选择项的列表
setCellWidget(row:int, column:int, widget:QWidget) -> None # 设置单元格的控件
cellWidget(row:int, column:int) -> QWidget # 获取单元格的控件
removeCellWidget(row:int, column:int) -> None # 移除单元格的控件
setSortingEnabled(enable:bool) -> None # 设置表格控件是否可以排序
isSortingEnabled() -> bool # 返回表格控件是否可以排序
sortItems(order:Qt.SortOrder=Qt.AscendingOrder) -> None # 按照排序方式进行项的排序
supportedDropActions() -> Qt.DropAction # 返回支持的拖动和粘贴操作
# 槽函数
insertRow(row:int) -> None # 在指定位置插入行
removeRow(row:int) -> None # 移除指定行
insertColumn(column:int) -> None # 在指定位置插入列
removeColumn(column:int) -> None # 移除指定列
clear() -> None # 清空表格项和表头的内容
clearContents() -> None # 清空表格项的内容
scrollToItem(item:QTableWidgetItem, hint=QAbstractItemView.ScrollHint.EnsureVisible) -> None # 滚动到指定项,使其可见
QTableWidget 类常用信号如下:
cellActivated(row:int, column:int) # 单元格活跃时发射信号
cellChanged(row:int, column:int) # 单元格数据变化时发射信号
cellClicked(row:int, column:int) # 单击单元格时发射信号
cellDoubleClicked(row:int, column:int) # 双击单元格时发射信号
cellEntered(row:int, column:int) # 光标进入单元格时发射信号
cellPressed(row:int, column:int) # 光标在单元格按下按键时发射信号
currentCellChanged(currentRow:int, currentColumn:int, previousRow:int, previousColumn:int) # 当前单元格改变时发射信号
currentItemChanged(current:QTableWidgetItem, previous:QTableWidgetItem) # 当前表格项改变时发射信号
itemActivated(item:QTableWidgetItem) # 表格项活跃时发射信号
itemChanged(item:QTableWidgetItem) # 表格项数据变化时发射信号
itemClicked(item:QTableWidgetItem) # 单击表格时发射信号
itemDoubleClicked(item:QTableWidgetItem) # 双击表格时发射信号
itemEntered(item:QTableWidgetItem) # 光标进入表格时发射信号
itemPressed(item:QTableWidgetItem) # 光标在表格按下按键时发射信号
itemSelectionChanged() # 选择的表格项发射改变时发射信号
QTableWidgetItem 类常用方法如下:
setText(text:str) -> None # 设置文字
text() -> str # 获取文字
setTextAlignment(alignment:Qt.Alignment) -> None # 设置文字对齐方式
setIcon(icon:QIcon) -> None # 设置图标
icon() -> QIcon # 获取图标
setToolTip(toolTip:str) -> None # 设置提示文字
setFont(font:QFont) -> None # 设置字体
setForeground(brush:QColor) -> None # 设置前景色
setBackground(brush:QColor) -> None # 设置背景色
setStatusTip(statusTip:str) -> None # 设置状态提示文字,需激活mouseTracking属性
setWhatsThis(whatsThis:str) -> None # 设置按Shift+F1键的显示文字
setCheckState(state:Qt.CheckState) -> None # 设置勾选状态
checkState() -> Qt.CheckState # 获取勾选状态
setFlags(flags:Qt.ItemFlag) -> None # 设置标识
setSelected(select:bool) -> None # 设置是否选中
isSelected() -> bool # 获取是否选中
clone() -> QTableWidgetItem # 克隆一个项
tableWidget() -> QTableWidget # 获取表格视图
write(out:QDataStream) -> None # 将项写入数据流
read(in:QDataStream) -> None # 从数据流中读取项
setData(role:int, value:Any) -> None # 设置某角色的数据
data(role:int) -> Any # 获取某角色的数据
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtWidgets import QTableWidget, QTableWidgetItem
class MyWidget(QWidget):
def __init__(self):
# 1.调用父类Qwidget类的__init__()方法
super().__init__()
# 2.调用setupUi()方法初始化页面
self.setup_ui()
def setup_ui(self):
# 1.设置窗口对象大小
self.resize(700, 500)
# 2.创建表格控件对象
self.tableWidget = QTableWidget(self)
self.tableWidget.resize(700, 500)
# 3.设置表格的行数
self.tableWidget.setRowCount(3)
# 4.设置表格的列数
self.tableWidget.setColumnCount(4)
# 5.设置表格的水平表头
self.tableWidget.setHorizontalHeaderLabels(["部门", "姓名", "性别", "年龄"])
# 6.设置表格的垂直表头
self.tableWidget.setVerticalHeaderLabels(["1", "2", "3"])
department_list = ["魔法部", "超能力部"]
person_list = [
{"department": department_list[0], "name": "木之本樱", "gender": "女", "age": 10},
{"department": department_list[0], "name": "夏娜", "gender": "女", "age": 15},
{"department": department_list[1], "name": "御坂美琴", "gender": "女", "age": 14},
]
for i in range(0, len(person_list)):
j = 0
for key, value in person_list[i].items():
item = QTableWidgetItem(str(value))
# 7.设置单元格的内容
self.tableWidget.setItem(i, j, item)
j += 1
# 8.设置表格列的宽度跟随内容改变
self.tableWidget.resizeColumnsToContents()
# 9.设置表格行的高度跟随内容改变
self.tableWidget.resizeRowsToContents()
# 10.设置单元格是否可以编辑
self.tableWidget.setEditTriggers(QTableWidget.EditTrigger.DoubleClicked)
# 11.设置表格颜色交错显示
self.tableWidget.setAlternatingRowColors(True)
# 12.设置表格的选择行为
self.tableWidget.setSelectionBehavior(QTableWidget.SelectionBehavior.SelectItems)
# 13.设置是否自动换行
self.tableWidget.setWordWrap(True)
# 14.设置是否显示网格
self.tableWidget.setShowGrid(True)
# 15.合并单元格
self.tableWidget.setSpan(0, 0, 2, 1)
# 16.定义信号与槽的连接
self.tableWidget.itemClicked.connect(self.itemClicked)
self.tableWidget.itemDoubleClicked.connect(self.itemDoubleClicked)
self.tableWidget.itemChanged.connect(self.itemChanged)
self.tableWidget.itemSelectionChanged.connect(self.itemSelectionChanged)
self.tableWidget.cellClicked.connect(self.cellClicked)
self.tableWidget.cellDoubleClicked.connect(self.cellDoubleClicked)
self.tableWidget.cellChanged.connect(self.cellChanged)
self.tableWidget.currentCellChanged.connect(self.currentCellChanged)
def itemClicked(self, item):
print(f"【{item.text()}】表格项被单击了")
def itemDoubleClicked(self, item):
print(f"【{item.text()}】表格项被双击了")
def itemChanged(self, item):
print(f"【{item.text()}】表格项内容被更改了")
def itemSelectionChanged(self):
print("你选中的表格项更改了")
def cellClicked(self, row, column):
item = self.tableWidget.item(row, column)
print(f"【{item.text()}】单元格被单击了")
def cellDoubleClicked(self, row, column):
item = self.tableWidget.item(row, column)
print(f"【{item.text()}】单元格被双击了")
def cellChanged(self, row, column):
item = self.tableWidget.item(row, column)
print(f"【{item.text()}】单元格内容被更改了")
def currentCellChanged(self, current_row, current_column, previous_row, previsou_column):
previous_item = self.tableWidget.item(previous_row, previsou_column)
current_item = self.tableWidget.item(current_row, current_column)
if previous_item:
previous_item_text = previous_item.text()
else:
previous_item_text = None
current_item_text = current_item.text()
print(f"你选中的单元格从【{previous_item_text}】变成了【{current_item_text}】")
if __name__ == "__main__":
# 1.创建一个QApplication类的实例
app = QApplication(sys.argv)
# 2.创建一个窗口
window = MyWidget()
# 3.展示窗口
window.show()
# 4.进入程序的主循环并通过exit()函数确保主循环安全结束
sys.exit(app.exec())
1.4 树控件及其项
树结构控件 QTreeWidget 继承自 QTreeView 类,它是 QTreeView 的便利类。树结构控件由 1 列或多列构成,没有行的概念。树结构控件有 1 个或多个顶层项,顶层项下面有任意多个子项,子项下面还可以有子项,顶层项没有父项。顶层项和子项都是 QTreeWidgetItem,每个 QTreeWidgetItem 可以定义在每列显示的文字和图标,一般应在第 1 列中定义文字或图标,其他列中是否设置文字和图标,需要用户视情况而定。可以把每个项理解成树结构控件的一行,只不过行之间有层级关系,可以折叠和展开。
用 QTreeWidget 类创建树结构控件的方法如下。
QTreeWidget(parent:QWidget=None)
其中 parent 是 QTreeWidget 树结构控件所在的父窗口或控件。
用 QTreeWidgetItem 类创建树结构项的方法如下。
QTreeWidgetItem(type=QTreeWidgetItem.Type)
QTreeWidgetItem(strings:Sequence[str], type=QTreeWidgetItem.Type)
QTreeWidgetItem(treeview:QTreeWidget, type=QTreeWidgetItem.Type)
QTreeWidgetItem(treeview:QTreeWidget, strings:Sequence[str], type=QTreeWidgetItem.Type)
QTreeWidgetItem(parent:QTreeWidgetItem, type=QTreeWidgetItem.Type)
QTreeWidgetItem(parent:QTreeWidgetItem, strings:Sequence[str], type=QTreeWidgetItem.Type)
QTreeWidgetItem(parent:QTreeWidgetItem, after:QTreeWidgetItem, type=QTreeWidgetItem.Type)
其中 Sequence[str] 表示字符串序列,是各列上的文字。第 1 个参数是 QTreeWidget 时表示项追加到树结构控件中,这时新创建的项是顶层项;第 1 个参数是 QTreeWidgetItem 表示父项,这时新创建的项作为子项追加到父项下面;第 2 个参数是 QTreeWidgetItem 时表示新创建的项插入到该项的后面。type 可以取 QTreeWidgetItem.Type(值是 0)或 QTreeWidgetItem.UserType(值是 1000,自定义类型的最小值)。
QTreeWidget 类常用方法如下:
# 实例方法
setColumnCount(columns:int) -> None # 设置列数
columnCount() -> int # 获取列数
currentColumn() -> int # 返回当前列
setColumnWidth(column:int, width:int) -> None # 设置列宽
setColumnHidden(column:int, hide:bool) -> None # 设置列是否隐藏
addTopLevelItem(item:QTreeWidgetItem) -> None # 添加顶层项
addTopLevelItems(items:Sequence[QTreeWidgetItem]) -> None # 添加多个顶层项
insertTopLevelItem(index:int, item:QTreeWidgetItem) -> None # 插入顶层项
insertTopLevelItems(index:int, items:Sequence[QTreeWidgetItem]) -> None # 插入多个顶层项
takeTopLevelItem(index:int) -> QTreeWidgetItem # 移除并获取顶层项
topLevelItem(index:int) -> QTreeWidgetItem # 返回索引是index的顶层项
topLevelItemCount() -> int # 返回顶层项的数量
indexOfTopLevelItem(item:QTreeWidgetItem) -> int # 返回顶层项的索引
setCurrentItem(item:QTreeWidgetItem) -> None # 把指定的项设置为当前项
setCurrentItem(item:QTreeWidgetItem, column:int) -> None # 设置当前项和当前列
currentItem() -> QTreeWidgetItem # 获取当前项
editItem(item:QTreeWidgetItem, column:int=0) -> None # 编辑表格项
openPersistentEditor(item:QTreeWidgetItem, column:int) -> None # 打开指定项的编辑框,用于编辑文本
isPersistentEditorOpen(item:QTreeWidgetItem, column:int) -> bool # 返回指定项的编辑框是否打开
closePersistentEditor(item:QTreeWidgetItem, column:int) -> None # 关闭指定项的编辑框
findItems(text:str, flags:Qt.MatchFlg, column:int=0) -> List[QTreeWidgetItem] # 获取满足条件项的列表
setHeaderItem(item:QTreeWidgetItem) -> None # 设置表头
setHeaderLabel(label:str) -> None # 设置表头的第一列文字
itemAt(p:QPoint) -> QTableWidgetItem # 获取指定位置处的表格项
itemAt(x:int, y:int) -> QTableWidgetItem # 获取指定位置处的表格项
invisibleRootItem() -> QTreeWidgetItem # 获取根项
itemAbove(item:QTreeWidgetItem) -> QTreeWidgetItem # 返回指定项之前的项
itemBelow(item:QTreeWidgetItem) -> QTreeWidgetItem # 返回指定项之后的项
selectedItems() -> List[QTreeWidgetItem] # 返回选择项的列表
setItemWidget(item:QTreeWidgetItem, column:int, widget:QWidget) -> None # 在指定项的指定列设置控件
itemWidget(item:QTreeWidgetItem, column:int) -> QWidget # 获取项上的控件
removeItemWidget(item:QTreeWidgetItem, column:int) -> None # 移除项上的控件
# 槽函数
scrollToItem(item:QTreeWidgetItem, hint=QAbstractItemView.ScrollHint.EnsureVisible) -> None # 滚动到指定项,使其可见
collapseItem(item:QTreeWidgetItem) -> None # 折叠项
collapseAll() -> None # 折叠所有项
expandItem(item:QTreeWidgetItem) -> None # 展开项
expandAll() -> None # 展开所有项
clear() -> None # 清空所有项
QTreeWidget 类常用信号如下:
currentItemChanged(current:QTreeWidgetItem, previous:QTreeWidgetItem) # 当前项改变时发射信号
itemActivated(item:QTreeWidgetItem, column:int) # 项活跃时发射信号
itemChanged(item:QTreeWidgetItem, column:int) # 项数据变化时发射信号
itemClicked(item:QTreeWidgetItem, column:int) # 单击项时发射信号
itemDoubleClicked(item:QTreeWidgetItem, column:int) # 双击项时发射信号
itemEntered(item:QTreeWidgetItem, column:int) # 光标进入项时发射信号
itemPressed(item:QTreeWidgetItem, column:int) # 在项上按下按键时发射信号
itemExpanded(item:QTreeWidgetItem) # 展开项时发射信号
itemCollapsed(item:QTreeWidgetItem) # 折叠项时发射信号
itemSelectionChanged() # 选择的项发射改变时发射信号
QTreeWidgetItem 类常用方法如下:
addChild(child:QTreeWidgetItem) -> None # 添加子项
addChildren(children:Sequence[QTreeWidgetItem]) -> None # 添加多个子项
insertChild(index:int, child:QTreeWidgetItem) -> None # 插入子项
insertChildren(index:int, children:Sequence[QTreeWidgetItem]) -> None # 插入多个子项
child(index:int) -> QTreeWidgetItem # 获取子项
childCount() -> int # 获取子项数量
takeChild(index:int) -> QTreeWidgetItem # 移除并返回子项
takeChildren() -> List[QTreeWidgetItem] # 移除并返回所有子项
removeChild(child:QTreeWidgetItem) -> None # 移除子项
parent() -> QTreeWidgetItem # 获取父项
treeWidget() -> QTreeWidget # 获取树视图
setText(column:int, text:str) -> None # 设置文字
text(column:int) -> str # 获取文字
setTextAlignment(column:int, alignment:Qt.Alignment) -> None # 设置文字对齐方式
setIcon(column:int, icon:QIcon) -> None # 设置图标
icon(column:int) -> QIcon # 获取图标
setToolTip(column:int, toolTip:str) -> None # 设置提示文字
setFont(column:int, font:QFont) -> None # 设置字体
font(column:int) -> QFont # 获取字体
setForeground(column:int, brush:QColor) -> None # 设置前景色
setBackground(column:int, brush:QColor) -> None # 设置背景色
setStatusTip(column:int, statusTip:str) -> None # 设置状态提示文字,需激活mouseTracking属性
setWhatsThis(column:int, whatsThis:str) -> None # 设置按Shift+F1键的显示文字
setCheckState(column:int, state:Qt.CheckState) -> None # 设置勾选状态
checkState(column:int) -> Qt.CheckState # 获取勾选状态
setFlags(flags:Qt.ItemFlag) -> None # 设置标识
setSelected(select:bool) -> None # 设置是否选中
isSelected() -> bool # 获取是否选中
setHidden(hide:bool) -> None # 设置是否隐藏
setDisabled(disabled:bool) -> None # 设置是否禁用
isDisabled() -> bool # 获取是否禁用
setExpanded(expand:bool) -> None # 设置是否展开
isExpanded() -> bool # 获取是否展开
setFirstColumnSpanned(span:bool) -> None # 设置是否只显示第一列的内容
setChildIndicatorPolicy(policy:QTreeWidgetItem.ChildIndicatorPolicy) -> None # 设置展开/折叠标识的显示策略
childIndicatorPolicy() -> QTreeWidgetItem.ChildIndicatorPolicy # 获取展开策略
columnCount() -> int # 获取列数
indexOfChild(child:QTreeWidgetItem) -> int # 获取子项的索引
sortChildren(column:int, order:Qt.SortOrder) -> None # 对子项进行排序
setData(column:int, role:int, value:Any) -> None # 设置某角色的数据
data(column:int, role:int) -> Any # 获取某角色的数据
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtWidgets import QTreeWidget, QTreeWidgetItem
from PySide6.QtGui import QPixmap, Qt
class MyWidget(QWidget):
def __init__(self):
# 1.调用父类Qwidget类的__init__()方法
super().__init__()
# 2.调用setupUi()方法初始化页面
self.setup_ui()
def setup_ui(self):
# 1.设置窗口对象大小
self.resize(700, 500)
# 2.创建树控件
treeWidget = QTreeWidget(self)
treeWidget.resize(700, 500)
# 3.设置列标题名
treeWidget.setHeaderLabels(["部门", "姓名", "性别", "年龄"])
# 4.设置树结构中的列数
treeWidget.setColumnCount(4)
# 5.设置列的宽度
treeWidget.setColumnWidth(0, 100)
department_list = ["魔法部", "超能力部"]
person_list = [
{"name": "木之本樱", "gender": "女", "age": 10, "department": department_list[0]},
{"name": "御坂美琴", "gender": "女", "age": 14, "department": department_list[1]},
{"name": "夏娜", "gender": "女", "age": 15, "department": department_list[0]},
]
for department in department_list:
# 一级节点
department_item = QTreeWidgetItem(treeWidget)
department_item.setText(0, department)
# 6.添加顶级节点
treeWidget.addTopLevelItem(department_item)
for person in person_list:
# 二级节点
if person["department"] == department:
person_item = QTreeWidgetItem(department_item)
# 7.设置节点的文本
person_item.setText(0, "")
# 8.设置节点的图标
person_item.setIcon(0, QPixmap("1.ico"))
# 9.设置节点的选中状态
person_item.setCheckState(0, Qt.CheckState.Unchecked)
i = 1
for key, value in person.items():
if not key == "department":
person_item.setText(i, str(value))
if value == "木之本樱":
person_item.setCheckState(0, Qt.CheckState.Checked)
i += 1
# 10.设置单击头部时是否可以排序
treeWidget.setSortingEnabled(True)
# 11.设置是否显示垂直滚动条
treeWidget.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
# 12.设置是否显示水平滚动条
treeWidget.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
# 13.设置每间隔一行颜色是否一致
treeWidget.setAlternatingRowColors(True)
# 14.设置是否自动换行
treeWidget.setWordWrap(False)
# 15.设置是否支持双击展开树节点
treeWidget.setExpandsOnDoubleClick(True)
# 16.设置选中模式
treeWidget.setSelectionMode(QTreeWidget.SelectionMode.ExtendedSelection)
# 17.设置选中方式
treeWidget.setSelectionBehavior(QTreeWidget.SelectionBehavior.SelectItems)
# 18.设置自动展开的时间,单位为毫秒,如果值小于0,表示禁用自动展开
treeWidget.setAutoExpandDelay(-1)
# 19.展开所有节点
treeWidget.expandAll()
# 20.定义信号与槽的连接
treeWidget.itemClicked.connect(self.itemClicked)
treeWidget.currentItemChanged.connect(self.currentItemChanged)
treeWidget.itemExpanded.connect(self.itemExpanded)
treeWidget.itemCollapsed.connect(self.itemCollapsed)
def itemClicked(self, item, column):
print(f"你单击了【{item.text(column)}】")
def currentItemChanged(self, current, previous):
current_text = current.text(0)
previous_text = previous.text(0) if previous else None
print(f"你选中的项从【{previous_text}】变成了【{current_text}】")
def itemExpanded(self, item):
print(f"你展开了【{item.text(0)}】项")
def itemCollapsed(self, item):
print(f"你收缩了【{item.text(0)}】项")
if __name__ == "__main__":
# 1.创建一个QApplication类的实例
app = QApplication(sys.argv)
# 2.创建一个窗口
window = MyWidget()
# 3.展示窗口
window.show()
# 4.进入程序的主循环并通过exit()函数确保主循环安全结束
sys.exit(app.exec())
参考链接:https://www.cnblogs.com/kurome/p/17871989.html
2.模型与视图
2.1 模型
对于存储在本机上的数据,我们可以先把数据读取到一个能保存数据的类中,或者类不直接读取数据,但能提供读取数据的接口,然后用能显示数据的控件把数据从模型中读取并显示出来,显示数据的控件并不存储数据,显示的数据只是数据的一个映射。像这种能保存数据或者能提供数据接口的类称为 数据模型(model),把数据模型中的数据显示出来的控件称为 视图控件 (view)。
要修改或增删视图控件中显示的数据,一种方法是在后台的数据模型中直接修改或增删数据,数据模型中的数据改变了,视图控件中显示的数据也会同时改变,视图控件不直接编辑数据,视图控件显示的数据只是对数据模型中数据的一种映射,是单向的;另一种方法是调用可以编辑数据的控件,在编辑控件中修改数据,修改完成后,通过信号通知数据模型和视图控件,数据模型中的数据和视图控件显示的数据也同时发生改变,像这种用于编辑数据的控件称为 代理控件。
2.2 数据模型的类型
根据用途不同,数据模型分为多种类型,QAbstractItemModel 是所有数据模型的基类。
数据模型存储数据的 3 种常见结构形式,主要有 列表模型(list model)、表格模型(table model)和 树模型(tree model)。列表模型中的数据没有层级关系,由一列多行数据构成;表格模型由多行多列数据构成;树结构模型的数据是有层级关系的,每层数据下面还有子层数据。
不管数据的存储形式如何,每个数据都称为 数据项(data item)。数据项存储不同角色、不同用途的数据,每个数据项都有一个索引(model index),通过数据索引可以获取数据项上存储的数据。
数据模型中存放着数据,要获取或写入数据,需要知道数据所在的行和列。行和列单独构成一个类,称为 数据项索引 QModelIndex,通过数据项索引可以定位到对应的数据。由于数据模型可能是一个列表、表格、树或更复杂的结构,所以数据模型的数据索引也会比较复杂。通常用 QModelIndex() 表示指向数据模型根部的索引,这个索引不指向任何数据,表示最高层索引。用数据模型的 index(row,column,parent) 表示索引 parent(类型是 QModelIndex)下的第 row 行第 column 列的数据项索引。
数据索引常用的方法如下:
model() -> QAbstractItemModel # 获取数据模型
parent() -> QModelIndex # 获取父索引
sibling(row:int, column:int) -> QModelIndex # 获取兄弟索引
siblingAtRow(row:int) -> QModelIndex # 获取指定行的兄弟索引
siblingAtColumn(column:int) -> QModelIndex # 获取指定列的兄弟索引
row() -> int # 获取行索引
column() -> int # 获取列索引
data(role:int=Qt.DisplayRole) -> Any # 获取数据相关指定角色的数据
flags() -> Qt.ItemFlag # 获取标识
isValid() -> bool # 判断索引是否有效
用 parent()
方法可以获得父数据项的索引;用 sibling(row,column)
方法、siblingAtColumn(column)
方法和 siblingAtRow(row)
方法可以获取同级别的 row 行 column 列的数据项的索引;用 isValid()
方法可以判断索引是否有效;用 row()
方法和 column()
方法可以获取数据索引所指向的行值和列值;用 flags()
方法获取数据项的状态,返回值是 Qt.ItemFlag 的枚举值,可取值如下:
Qt.ItemFlag.NoItemFlags # 没有任何属性
Qt.ItemFlag.ItemIsSelectable # 可选择
Qt.ItemFlag.ItemIsEditable # 可编辑
Qt.ItemFlag.ItemIsDragEnabled # 可拖拽
Qt.ItemFlag.ItemIsDropEnabled # 可拖放
Qt.ItemFlag.ItemIsUserCheckable # 可勾选
Qt.ItemFlag.ItemIsEnabled # 可激活
Qt.ItemFlag.ItemIsAutoTristate # 由子项的状态决定
Qt.ItemFlag.ItemNeverHasChildren # 禁止有子项
Qt.ItemFlag.ItemIsUserTristate # 用户可以在3种状态间切换
3.抽象模型与抽象视图
3.1 抽象模型
抽象模型 QAbstractItemModel 提供数据模型与视图控件的数据接口,不能直接使用该类,需要用其子类定义数据模型。QAbstractItemModel 的方法会被其子类继承。
QAbstractItemModel 类常用方法:
index(row:int, column:int, parent:QModelIndex=QModelIndex()) -> QModelIndex # 获取父索引下的指定行和列的数据索引项
parent(child:QModelIndex) -> QModelIndex # 获取指定索引项的父索引项
sibling(row:int, column:int, idx:QModelIndex) -> QModelIndex # 获取指定索引项的指定行和列的数据索引项
flags(index:QModelIndex) -> Qt.ItemFlag # 获取指定索引项的标识
hasChildren(parent:QModelIndex=QModelIndex()) -> bool # 判断是否有子数据项
hasIndex(row:int, column:int, parent:QModelIndex=QModelIndex()) -> bool # 判断是否能创建数据索引项
rowCount(parent:QModelIndex=QModelIndex()) -> int # 获取行数
columnCount(parent:QModelIndex=QModelIndex()) -> int # 获取行数
insertRow(row:int, parent:QModelIndex=QModelIndex()) -> bool # 插入行,成功返回True
insertRows(row:int, count:int, parent:QModelIndex=QModelIndex()) -> bool # 插入多行,成功返回True
insertColumn(column:int, parent:QModelIndex=QModelIndex()) -> bool # 插入列,成功返回True
insertColumns(column:int, count:int, parent:QModelIndex=QModelIndex()) -> bool # 插入多列,成功返回True
setData(index:QModelIndex, value:Any, role:Qt.ItemDataRole=Qt.EditRole) -> bool # 设置数据,成功返回True
data(index:QModelIndex, role:Qt.ItemDataRole=Qt.EditRole) -> Any # 获取数据
setItemData(index:QModelIndex, role:Dict[int, Any]) -> bool # 设置数据,成功返回True
itemData(index:QModelIndex) -> Any # 获取数据
clearItemData(index:QModelIndex) -> bool # 清除项中的数据
setHeaderData(section:int, orientation:Qt.Orientation, value:Any, role:int=Qt.EditRole) -> bool # 设置表头数据,成功返回True
headerData(section:int, orientation:Qt.Orientation, role:int=Qt.EditRole) -> Any # 获取表头数据Any
supportedDragActions() -> Qt.DropActions # 获取支持的拖放动作
sort(column:int, order:Qt.SortOrder=Qt.AscendingOrder) -> None # 排序
submit() -> None # 提交缓存数据到永久存储中
revert() -> None # 放弃提交缓存数据到永久存储中
# 移动单行,成功返回True
moveRow(sourceParent:QModelIndex, sourceRow:int, destinationParent:QModelIndex, destinationRow:int) -> bool
# 移动多行,成功返回True
moveRows(sourceParent:QModelIndex, sourceRow:int, count:int, destinationParent:QModelIndex, destinationRow:int) -> bool
# 移除单行,成功返回True
removeRow(row:int, parent:QModelIndex=QModelIndex()) -> bool
# 移除多行,成功返回True
removeRows(row:int, count:int, parent:QModelIndex=QModelIndex()])
# 将目标数据项索引的指定列移动到目标数据项索引的指定列处,成功返回True
moveColumn(sourceParent:QModelIndex, sourceColumn:int, destinationParent:QModelIndex, destinationColumn:int) -> bool
# 移动多列到目标索引的指定列处,成功返回True
moveColumns(sourceParent:QModelIndex, sourceColumn:int, count:int, destinationParent:QModelIndex, destinationColumn:int) -> bool
# 移除单列,成功返回True
removeColumn(column:int, parent:QModelIndex=QModelIndex()) -> bool
# 移除多列,成功返回True
removeColumns(column:int, count:int, parent:QModelIndex=QModelIndex())
用 setData(QModelIndex,Any,role=Qt.ItemDataRole)
方法可以设置数据项的某角色值,用 setItemData(QModelIndex,roles:Dict[int,Any])
方法可以用字典方式设置某数据项的多个角色值,用 data(QModelIndex,role=Qt.ItemDataRole)
和 itemData(QModelIndex)
方法获取角色值,其中参数 Qt.ItemDataRole 的取值如下所示。
Qt.ItemDataRole 取值 | 值 | 对应的数据类型 | 说明 |
---|---|---|---|
Qt.ItemDataRole.DisplayRole | 0 | str | 视图控件显示文本 |
Qt.ItemDataRole.DecorationRole | 1 | QIcon、QPixmap | 图标 |
Qt.ItemDataRole.EditRole | 2 | str | 视图控件中编辑是显示文本 |
Qt.ItemDataRole.ToolTipRole | 3 | str | 提示信号 |
Qt.ItemDataRole.StatusTipRole | 4 | str | 状态提示信息 |
Qt.ItemDataRole.WhatsThisRole | 5 | str | 按下 Shift+F1 键时显示的数据 |
Qt.ItemDataRole.FontRole | 6 | QFont | 默认代理控件的字体 |
Qt.ItemDataRole.TextAlignmentRole | 7 | Qt.AlignmentFlag | 默认代理控件的对齐方式 |
Qt.ItemDataRole.BackgroundRole | 8 | QBrush、QColor、Qt.GlobalColor | 默认代理控件的背景色 |
Qt.ItemDataRole.ForegroundRole | 9 | QBrush、QColor、Qt.GlobalColor | 默认代理控件的前景色 |
Qt.ItemDataRole.CheckStateRole | 10 | Qt.CheckState | 勾选状态 |
Qt.ItemDataRole.AccessibleTextRole | 11 | str | 用于可访问插件扩展的文本 |
Qt.ItemDataRole.AccessibleDescriptionRole | 12 | str | 用于可访问功能的描述 |
Qt.ItemDataRole.SizeHintRole | 13 | QSize | 尺寸提示 |
Qt.ItemDataRole.InitialSortOrderRole | 14 | Qt.SortOrder | 初始排序 |
Qt.ItemDataRole.UserRole | 0x0100 | Any | 自定义角色,可使用多个自定义角色,第 1 个为 Qt.UserRole,第 2 个为 Qt.UserRole+1,依次类推 |
用 setHeaderData(section:int,orientation:Qt.Orientation,value:Any,role:int=Qt.EditRole)
方法设置表头某角色的值,当 orientation 取 Qt.Horizontal 时,section 是指列;orientation 取 Qt.Vertical 时,section 是指行。
QAbstractItemModel 类常用信号:
# 插入行之前发射信号
rowsAboutToBeInserted(parent:QModelIndex, first:int, last:int)
# 插入行之后发射信号
rowsInserted(parent:QModelIndex, first:int, last:int)
# 移动行之前发射信号
rowsAboutToBeMoved(sourceParent:QModelIndex, sourceStart:int, sourceEnd:int, destinationParent:QModelIndex, destinationRow:int)
# 移动行之后发射信号
rowsMoved(sourceParent:QModelIndex, sourceStart:int, sourceEnd:int, destinationParent:QModelIndex, destinationRow:int)
# 移除行之前发射信号
rowsAboutToBeRemoved(parent:QModelIndex, first:int, last:int)
# 移除行之后发射信号
rowsRemoved(parent:QModelIndex, first:int, last:int)
# 插入列之前发射信号
columnsAboutToBeInserted(parent:QModelIndex, first:int, last:int)
# 插入列之后发射信号
columnsInserted(parent: QModelIndex, first:int, last:iint)
# 移动列之前发射信号
columnsAboutToBeMoved(sourceParent:QModelIndex, sourceStart:int, sourceEnd:int, destinationParent:QModelIndex, destinationColumn:int)
# 移动列之后发射信号
columnsMoved(sourceParent:QModelIndex, sourceStart:int, sourceEnd:int, destinationParent:QModelIndex, destinationColumn:int)
# 移除列之后发射信号
columnsAboutToBeRemoved(parent:QModelIndex, first:int, last:int)
# 移除列之后发射信号
columnsRemoved(parent:QModelIndex, first:int, last:int)
# 数据改变之前发射信号
dataChanged(topLeft:QModelIndex, topRight:QModelIndex, roles:List[int]=list())
# 数据改变之后发射信号
headerDataChanged(orientation:Qt.Orientation, first:int, last:int)
# 重置之前发射信号
modelAboutToBeReset()
# 重置之后发射信号
modelReset()
3.2 抽象视图
所有的视图都继承于 QAbstractItemView 类。
QAbstractItemView 类常用的方法如下:
# 实例方法
setModel(model:QAbstractItemModel) -> None # 设置数据模型
setSelectionModel(selectionModel:QItemSelectionModel) -> None # 设置选择模型
selectionModel() -> QItemSelectionModel # 获取选择模型
setSelection(rect:QRect, command:QItemSelectionModel.SelectionFlag) -> None # 选择指定范围内的数据项
setRootIndex(index:QModelIndex) -> None # 设置根索引
setAlternatingRowColors(enable:bool) -> None # 设置交替色
indexAt(point:QPoint) -> QModelIndex # 获取指定位置处数据项的模型数据索引
selectAll() -> None # 选择所有数据项
selectedIndexes() -> QModelIndexList # 获取所有选择项的模型数据索引
setTextElideMode(mode:Qt.TextElideMode) -> None # 设置省略号的位置
isIndexHidden(index:QModelIndex) -> bool # 获取索引对应的单元是否隐藏
# 使数据项可见
scrollTo(index:QModelIndex, hint:QAbstractItemView.ScrollHint=QAbstractItemView.ScrollHint.EnsureVisible) -> None
# 槽方法
clearSelection() -> None # 清空选择
用 setModel(QAbstractItemModel)
方法可以给视图控件设置关联的数据模型;用 setRootIndex(QModelIndex)
方法设置视图控件需要显示的数据索引下的子数据项。用 setSelectionMode(QAbstractItemView.SelectionMode)
方法可以设置选择模式,其中参数 QAbstractItemView.SelectionMode 的取值如下:
QAbstractItemView.SelectionMode.NoSelection # 进制选择
QAbstractItemView.SelectionMode.SingleSelection # 单选
QAbstractItemView.SelectionMode.MultiSelection # 多选
QAbstractItemView.SelectionMode.ExtendedSelection # 按Ctrl键点选,按Shift键连选
QAbstractItemView.SelectionMode.ContiguousSelection # 按Ctrl键或Shift键时连选
QAbstractItemView 类常用的信号如下:
activated(index:QModelIndex) # 数据项活跃时发射信号
clicked(index:QModelIndex) # 单击数据项时发射信号
doubleClicked(index:QModelIndex) # 双击数据项时发射信号
entered(index:QModelIndex) # 光标进入数据项时发射信号
iconSizeChanged(size:QSize) # 图标尺寸发生变化时发射信号
pressed(index:QModelIndex) # 按下鼠标时发射信号
viewportEntered() # 光标进入视口时发射信号
4.文本列表模型与列表视图
4.1 文本列表模型
文本列表模型 QStringListModel 通常用于存储一维文本列表,它由一列多行文本数据构成。用于显示 QStringListModel 模型中文本数据的控件是 QListView 控件。
用 QStringListModel 类创建文本列表模型实例的方法如下:
QStringListModel(parent:QWidget=None)
QStringListModel(strings:Sequence[str], parent:QWidget=None)
其中 parent 是继承自 QObject 的实例对象;strings 是字符串型列表或元组,用于确定文本列表模型中显示角色和编辑角色的数据。
文本列表模型 QStringListModel 类的常用方法如下:
setStringList(strings:Sequence[str]) -> None # 设置列表模型显示和编辑角色的文本数据
stringList() -> List[str] # 获取文本列表
4.2 列表视图控件
列表视图控件 QListView 用于显示文本列表模型 QStringListModel 中的文本数据。用 QListView 创建列表视图控件的方法如下:
QListView(parent:QWidget=None)
其中 parent 是继承自 QWidget 的窗口或容器控件。
列表视图控件 QListView 用于显示数据模型中某数据项下的所有子数据项的显示角色的文本。列表视图控件没有表头,可以把数据显示成一列,也可以显示成一行。列表视图控件不仅可以显示文本列表模型中的数据,也可显示其他模型中的数据。
列表视图控件 QListView 类的常用方法如下:
clearPropertyFlags() -> None # 清空所有属性标志
contentsSize() -> QSize # 获取内容尺寸
resizeContents(width:int, height:int) -> None # 调整内容尺寸
setModelColumn(column:int) -> None # 设置模型列
modelColumn() -> int # 获取模型列
setWordWrap(on:bool) -> None # 设置单词是否可以写到两行上
setWrapping(enable:bool) -> None # 设置文本是否可以写到两行上
setFlow(flow:QListView.Flow) -> None # 设置显示方向
setGridSize(size:QSize) -> None # 设置网格尺寸
setItemAlignment(alignment:Qt.Alignment) -> None # 设置项对齐方式
setLayoutMode(mode:QListView.LayoutMode) -> None # 设置数据的显示模式
setBatchSize(batchSize:int) -> None # 设置批量显示的数量,默认100
setMovement(movement:QListView.Movement) -> None # 设置数据项的移动方式
setResizeMode(mode:QListView.ResizeMode) -> None # 设置数据项的大小调整方式
setRowHidden(row:int, hide:bool) -> None # 设置指定行是否可见
setSpacing(space:int) -> None # 设置数据项之间的间距
setUniformItemSizes(enable:bool) -> None # 设置所有数据项的大小是否一致
setViewMode(mode:QListView.ViewMode) -> None # 设置显示模式
setPositionForIndex(position:QPoint, index:QModelIndex) -> None # 将指定索引的项放到指定位置处
用 setFlow(QListView.Flow)
方法设置数据项的排列方向,其中 QListView.Flow 可以取值如下:
QListView.Flow.LeftToRight # 值是0
QListView.Flow.TopToBottom # 值是1
用 setLayoutMode(QListView.LayoutMode)
方法设置数据的显示方式,其中 QListView.LayoutMode 可取值如下:
QListView.LayoutMode.SinglePass # 值是0,全部显示
QListView.LayoutMode.Batched # 值是1,分批显示
用 setMovement(QListView.Movement)
方法设置数据项的拖拽方式,其中 QListView.Movement 可取值如下:
QListView.Movement.Static # 不能移动
QListView.Movement.Free # 可以自由移动
QListView.Movement.Snap # 捕捉到数据项的位置
用 setViewMode(QListView.ViewMode)
方法设置显示模式,参数 QListView.ViewMode 可以取值如下:
QListView.ViewMode.ListMode # 采用QListView.TopToBottom排列、小尺寸和QListView.Static不能移动方式
QListView.ViewMode.IconMode, # 采用QListView.LeftToRight排列、大尺寸和QListView.Free自由移动方式
用 setResizeMode(QListView.ResizeMode)
方法设置尺寸调整模式,参数可取值如下:
QListView.ResizeMode.Fixed
QListView.ResizeMode.Adjust
列表视图控件 QListView 类的常用信号如下:
indexesMoved(indexes:List[QModelIndex]) # 数据索引发生移动时发射信号
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtWidgets import QListView
from PySide6.QtCore import QStringListModel
class MyWidget(QWidget):
def __init__(self):
# 1.调用父类Qwidget类的__init__()方法
super().__init__()
# 2.调用setupUi()方法初始化页面
self.setup_ui()
def setup_ui(self):
# 1.设置窗口对象大小
self.resize(700, 500)
# 2.创建数据模型
model = QStringListModel()
# 3.向模型中添加数据
names = ["木之本樱", "御坂美琴", "夏娜", "赤瞳", "黑瞳"]
model.setStringList(names)
# 4.创建列表视图对象
listView = QListView(self)
listView.resize(300, 100)
# 5.为视图设置模型
listView.setModel(model)
# 6.设置选择模式
listView.setSelectionMode(QListView.SelectionMode.ExtendedSelection)
# 7.设置选择项的方式
listView.setSelectionBehavior(QListView.SelectionBehavior.SelectItems)
# 8.设置显示模式
listView.setViewMode(QListView.ViewMode.IconMode)
# 9.设置是否自动换行
listView.setWordWrap(True)
# 10.定义信号与槽的连接
listView.clicked.connect(self.clicked)
listView.doubleClicked.connect(self.doubleClicked)
listView.entered.connect(self.entered)
listView.pressed.connect(self.pressed)
def clicked(self, index):
print(f"【{index.data()}】项被单击了")
def doubleClicked(self, index):
print(f"【{index.data()}】项被双击了")
def entered(self, index):
print(f"鼠标移入【{index.data()}】项")
def pressed(self, index):
print(f"【{index.data()}】项被按下了")
if __name__ == "__main__":
# 1.创建一个QApplication类的实例
app = QApplication(sys.argv)
# 2.创建一个窗口
window = MyWidget()
# 3.展示窗口
window.show()
# 4.进入程序的主循环并通过exit()函数确保主循环安全结束
sys.exit(app.exec())
5.文件系统模型与树视图
5.1 文件系统模型
利用文件系统模型 QFileSystemModel 可以访问本机的文件系统,可以获得文件目录、文件名称和文件大小等信息,可以新建目录、删除目录和文件、移动目录和文件及重命名目录和文件。
用 QFileSystemModel 类定义文件系统模型的方法如下所示:
QFileSystemModel(parent:QObject=None)
QFileSystemModel 类的常用方法如下:
setRootPath(path:str) -> QModelIndex # 设置模型的根目录,并返回指向该目录的模型数据索引
setFilter(filters:QDir.Filter) -> None # 设置路径过滤器
setNameFilters(filters:Sequence[str]) -> None # 设置文件名过滤器
nameFilters() -> List[str] # 获取名称过滤器
setNameFilterDisables(enable:bool) -> None # 设置名称过滤器是否激活
nameFilterDisables() -> bool # 获取名称过滤器是否激活
setOption(option:QFileSystemModel.Option, on:bool=true) -> None # 设置文件系统模型的参数
setReadOnly(enable:bool) -> None # 设置是否只读
isReadOnly() -> bool # 获取是否只读
fileIcon(index:QModelIndex) -> QIcon # 获取文件图标
fileInfo(index:QModelIndex) -> QFileInfo # 获取文件信息
fileName(index:QModelIndex) -> str # 获取文件名
filePath(index:QModelIndex) -> str # 获取文件路径
index(path:str, column:int=0) -> QModelIndex # 获取文件路径对应的索引
isDir(index:QModelIndex) -> bool # 获取是否为目录
lastModified(index:QModelIndex) -> QDateTime # 获取文件最后修改时间
mkdir(parent:QModelIndex, name:str) -> QModelIndex # 创建目录
myComputer(role:Qt.UserRole=Qt.DisplayRole) -> Any # 获取我的电脑的路径
remove(index:QModelIndex) -> bool # 删除文件或目录
rmdir(index:QModelIndex) -> bool # 删除目录
rootDirectory() -> QDir # 返回根目录
rootPath() -> str # 获取根目录路径
size(index:QModelIndex) -> int # 获取文件大小
type(index:QModelIndex) -> str # 获取文件类型
用 setRootPath(path:str)
方法设置模型的根目录,并返回指向该目录的模型数据索引。改变根目录时,发送 rootPathChanged(newPath)
信号。用 rootPath()
方法获取根目录。
用 setOption(QFileSystemModel.Option,on=True)
方法设置文件系统模型的参数,其中 QFileSystemModel.Option 可取值如下:
QFileSystemModel.Option.DontWatchForChanges # 不使用监控器,默认是关闭的
QFileSystemModel.Option.DontResolveSymlinks # 不解析链接,默认是关闭的
QFileSystemModel.Option.DontUseCustomDirectoryIcons # 不使用客户图标,默认是关闭的
用 setNameFilters(filters:Sequence[str])
方法设置名称过滤器;用 setFilter(filters:QDir.Filter)
方法设置路径过滤器,其中 filters 可取值如下:
QDir.Filter.Dirs
QDir.Filter.AllDirs
QDir.Filter.Files
QDir.Filter.Drives
QDir.Filter.NoSymLinks
QDir.Filter.NoDotAndDotDot
QDir.Filter.NoDot
QDir.Filter.NoDotDot
QDir.Filter.AllEntries
QDir.Filter.Readable
QDir.Filter.Writable
QDir.Filter.Executable
QDir.Filter.Modified
QDir.Filter.Hidden
QDir.Filter.System
QDir.Filter.CaseSensitive
设置路径过滤器时一定要包括 QDir.AllDirs,否则无法识别路径的结构。
QFileSystemModel 类的常用信号如下:
directoryLoaded(path:str) # 当加载路径时发射信号
fileRenamed(path:str, oldName:str, newName:str) # 当文件重命名时发射信号
rootPathChanged(newPath:str) # 根路径发生改变时发射信号
5.2 树视图
树视图控件 QTreeView 以树列表的形式显示文件系统模型关联的本机文件系统,显示出本机的目录、文件名、文件大小等信息,也可以以层级结构形式显示其他类型的数据模型。
用 QTreeView 类创建树视图控件的方法如下:
QTreeView(parent:QObject=None)
QTreeView 类常用方法如下:
# 实例方法
setRootIsDecorated(show:bool) -> None # 设置根部是否有折叠或展开标识
rootIsDecorated() -> bool # 获取根部是否有折叠或展开标识
indexAbove(index:QModelIndex) -> QModelIndex # 返回指定索引的之前的索引
indexBelow(index:QModelIndex) -> QModelIndex # 返回指定索引的之后的索引
setAnimated(enable:bool) -> None # 设置是否使用动画
isAnimated() -> bool # 获取是否使用动画
setColumnHidden(column:int, hide:bool) -> None # 设置指定列是否隐藏
isColumnHidden(column:int) -> bool # 获取指定列是否隐藏
setColumnWidth(column:int, width:int) -> None # 设置指定列的宽度
columnWidth(column:int) -> int # 获取指定列的宽度
setRowHidden(row:int, parent:QModelIndex, hide:bool) -> None # 设置相对于parent的第row是否隐藏
isRowHidden(row:int, parent:QModelIndex) -> bool # 获取相对于parent的第row是否隐藏
rowHeight(index:QModelIndex) -> int # 获取指定行的高度
setItemsExpandable(enable:bool) -> None # 设置是否允许展开和折叠
itemsExpandable() -> bool # 获取是否允许展开和折叠
setExpanded(index:QModelIndex, expand:bool) -> None # 设置是否展开指定的节点
setExpandsOnDoubleClick(enable:bool) -> None # 设置双击是否展开节点
setFirstColumnSpanned(row:int, parent:QModelIndex, span:bool) -> None # 设置某行的第一列的内容是否占据所有列
isFirstColumnSpanned(row:int, parent:QModelIndex) -> bool # 获取某行的第一列的内容是否占据所有列
setHeader(header:QHeaderView) -> None # 设置表头
header() -> QHeaderView # 获取表头
setHeaderHidden(hide:bool) -> None # 设置表头是否隐藏
setIndentation(i:int) -> None # 设置缩进
indentation() -> int # 获取缩进
resetIndentation() -> None # 重置缩进
setAutoExpandDelay(delay:int) -> None # 拖放操作中设置项打开的延迟时间(毫秒)
autoExpandDelay() -> int # 获取项打开的延迟时间,如果为负,则不能打开
setAllColumnsShowFocus(enable:bool) -> None # 设置所有列是否显示焦点
allColumnsShowFocus() -> bool # 获取所有列是否显示焦点
setUniformRowHeights(uniform:bool) -> None # 设置所有行的高度是否一致
uniformRowHeights() -> bool # 获取所有行的高度是否一致
setWordWrap(on:bool) -> None # 设置是否自动换行
setTreePosition(logicalIndex:int) -> None # 设置树位置
treePosition() -> int # 获取树位置
setSortingEnabled(enable:bool) -> None # 设置是否允许排序
isSortingEnabled() -> bool # 获取是否允许排序
# 槽方法
collapse(index:QModelIndex) -> None # 折叠指定的节点
collapseAll() -> None # 折叠所有节点
expand(index:QModelIndex) -> None # 展开指定的节点
expandAll() -> None # 展开所有节点
expandRecursively(index:QModelIndex, depth:int=-1) -> None # 逐级展开,展开深度是depth,-1表示展开所有节点,0表示只展开本层
expandToDepth(depth:int) -> None # 展开到指定深度
hideColumn(column:int) -> None # 隐藏指定列
showColumn(column:int) -> None # 显示指定列
sortByColumn(column:int, order:Qt.SortOrder) -> None # 按列进行排序
resizeColumnToContents(column:int) -> None # 根据内容调整列的尺寸
QTreeView 类常用信号如下:
collapsed(index:QModelIndex) # 折叠节点时发射信号
expanded(index:QModelIndex) # 展开节点时发射信号
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtWidgets import QTreeView, QFileSystemModel
from PySide6.QtCore import Qt
class MyWidget(QWidget):
def __init__(self):
# 1.调用父类Qwidget类的__init__()方法
super().__init__()
# 2.调用setupUi()方法初始化页面
self.setup_ui()
def setup_ui(self):
# 1.设置窗口对象大小
self.resize(700, 500)
# 2.创建文件系统模型对象
model = QFileSystemModel()
# 3.设置根路径为当前系统根目录
model.setRootPath("/")
# 4.创建树视图
treeView = QTreeView(self)
treeView.resize(700, 500)
# 5.设置要显示的数据模型
treeView.setModel(model)
# 6.设置是否隐藏头部
treeView.setHeaderHidden(False)
# 7.设置单击头部时是否可以排序
treeView.setSortingEnabled(True)
# 8.设置是否显示垂直滚动条
treeView.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
# 9.设置是否显示水平滚动条
treeView.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
# 10.设置每间隔一行颜色是否一致
treeView.setAlternatingRowColors(True)
# 11.设置是否自动换行
treeView.setWordWrap(False)
# 12.设置是否支持双击展开树节点
treeView.setExpandsOnDoubleClick(True)
# 13.设置选中模式
treeView.setSelectionMode(QTreeView.SelectionMode.ExtendedSelection)
# 14.设置选中方式
treeView.setSelectionBehavior(QTreeView.SelectionBehavior.SelectItems)
# 15.设置自动展开的时间,单位为毫秒,如果值小于0,表示禁用自动展开
treeView.setAutoExpandDelay(-1)
# 16.收缩所有节点
treeView.collapseAll()
# 17.定义信号与槽的连接
treeView.clicked.connect(self.clicked)
treeView.doubleClicked.connect(self.doubleClicked)
treeView.entered.connect(self.entered)
treeView.pressed.connect(self.pressed)
treeView.collapsed.connect(self.collapsed)
treeView.expanded.connect(self.expanded)
def clicked(self, index):
print(f"【{index.data()}】节点被单击了")
def doubleClicked(self, index):
print(f"【{index.data()}】节点被双击了")
def entered(self, index):
print(f"鼠标移入【{index.data()}】节点")
def pressed(self, index):
print(f"【{index.data()}】节点被按下了")
def collapsed(self, index):
print(f"你收缩了【{index.data()}】节点")
def expanded(self, index):
print(f"你展开了【{index.data()}】节点")
if __name__ == "__main__":
# 1.创建一个QApplication类的实例
app = QApplication(sys.argv)
# 2.创建一个窗口
window = MyWidget()
# 3.展示窗口
window.show()
# 4.进入程序的主循环并通过exit()函数确保主循环安全结束
sys.exit(app.exec())
6.标准数据模型与表格视图
6.1 标准数据模型
标准数据模型 QStandardItemModel 可以存储多行多列的数据表格,数据表格中的每个数据称为数据项 QStandardItem,每个数据项下面还可以存储多行多列的子数据表格,并形成层级关系,这样会形成比较复杂的结构关系。数据项可以存储文本、图标、勾选状态等信息。
用 QStandardItemModel 创建标准数据模型的方法如下所示:
QStandardItemModel(parent:QObject=None)
QStandardItemModel(rows:int, columns:int, parent:QObject=None)
QStandardItemModel 类的常用方法如下:
setRowCount(rows:int) -> None # 设置行的数量
setColumnCount(columns:int) -> None # 设置列的数量
appendRow(item:QStandItem) -> None # 添加行
appendRow(items:Sequence[QStandItem]) -> None # 添加行
appendColumn(items:Sequence[QStandItem]) -> None # 添加列
insertRow(row:int, item:QStandItem) -> None # 插入行
insertRow(row:int, items:Sequence[QStandItem]) -> None # 插入行
insertColumn(column:int, items:Sequence[QStandItem]) -> None # 插入列
takeRow(row:int) -> List[QStandItem] # 删除行
takeColumn(column:int) -> List[QStandItem] # 删除列
setItem(row:int, item:QStandItem) -> None # 根据行设置单元格的值
setItem(row:int, column:int, item:QStandItem) -> None # 根据行和列设置单元格的值
item(row:int, column:int=0) -> QStandItem # 根据行和列获取单元格的值
takeItem(row:int, column:int=0) -> QStandItem # 移除单元格
setHorizontalHeaderItem(column:int, item:QStandItem) -> None # 设置水平表头的项
horizontalHeaderItem(column:int) -> QStandItem # 获取水平表头的项
takeHorizontalHeaderItem(column:int) -> QStandItem # 移除水平表头的项
setVerticalHeaderItem(row:int, item:QStandItem) -> None # 设置垂直表头的项
verticalHeaderItem(row:int) -> QStandItem # 获取垂直表头的项
takeVerticalHeaderItem(row:int) -> QStandItem # 移除垂直表头的项
indexFromItem(item:QStandItem) -> QModelIndex # 根据项获取索引
itemFromIndex(index:QModelIndex) -> QStandItem # 根据索引获取项
invisibleRootItem() -> QStandItem # 获取根项
clear() -> None # 清空表格
findItems(text:str, flags:Qt.MatchFlag=Qt.MatchExactly, column:int=0) -> List[QStandItem] # 获取满足匹配条件的数据项列表
setSortRole(role:int) -> None # 设置排序角色
sortRole() -> int # 获取排序角色
6.2 数据项
用 QStandardItem 创建数据项的方法如下所示,用 QStandardItem(rows,columns) 方法可以创建一个含有多行多列子数据项的数据项。
QStandardItem()
QStandardItem(text:str)
QStandardItem(icon:Union[QIcon, QPixmap], text:str)
QStandardItem(rows:int, columns:int-1)
QStandardItem 类的常用方法如下:
index() -> QModelIndex # 获取数据项的索引
model() -> QAbstractItemModel # 获取模型
setRowCount(rows:int) -> None # 设置行数
rowCount() -> int # 获取行数
setColumnCount(columns:int) -> None # 设置列数
columnCount() -> int # 获取列数
setChild(row:int, item:QStandardItem) -> None # 根据行设置子数据项
setChild(row:int, column:int, item:QStandardItem) -> None # 根据行和列设置子数据项
hasChildren() -> bool # 是否有子数据项
child(row:int, column:int=0) -> QStandardItem # 获取子数据项
takeChild(row:int, column:int=0) -> QStandardItem # 移除并返回子项
parent() -> QStandardItem # 获取父数据项
row() -> int # 获取行号
column() -> int # 获取列号
appendRow(item:QStandardItem) -> None # 添加行
appendRow(items:Sequence[QStandardItem]) -> None # 添加行
appendRows(items:Sequence[QStandardItem]) -> None # 添加多行
insertRow(row:int, item:QStandardItem) -> None # 插入行
insertRows(row:int, count:int) -> None # 插入多行
insertRows(row:int, items:Sequence[QStandardItem]) -> None # 插入多行
removeRow(row:int) -> None # 移除行
removeRows(row:int, count:int) -> None # 移除多行
takeRow(row:int) -> List[QStandardItem] # 移除并返回行
appendColumn(items:Sequence[QStandardItem]) -> None # 添加列
insertColumn(column:int, items:Sequence[QStandardItem]) -> None # 插入列
insertColumns(column:int, count:int) -> None # 插入多列
removeColumn(column:int) -> None # 移除列
removeColumns(column:int, count:int) -> None # 移除多列
takeColumn(column:int) -> List[QStandardItem] # 移除并返回列
setAutoTristate(tristate:bool) -> None # 设置自动有第三种状态
isAutoTristate() -> bool # 获取是否自动有第三种状态
# 设置前景色
setForeground(brush:Union[QBrish, Qt.BrushStyle, Qt.GlobalColor, QColor, QGradint, QImage, QPixmap]) -> None
# 获取前景画刷
foreground() -> QBrush
# 设置背景色
setBackground(brush:Union[QBrish, Qt.BrushStyle, Qt.GlobalColor, QColor, QGradint, QImage, QPixmap]) -> None
# 获取背景画刷
background() -> QBrush
setCheckable(checkable:bool) -> None # 设置是否可选
setCheckState(checkState:Qt.CheckState) -> None # 设置选中状态
setDragEnabled(dragEnabled:bool) -> None # 设置是否可以拖拽
isDragEnabled() -> bool # 获取是否可以拖拽
setDropEnabled(dropEnabled:bool) -> None # 设置是否可以拖放
isDropEnabled() -> bool # 获取是否可以拖放
setEditable(editable:bool) -> None # 设置是否可以编辑
isEditable() -> bool # 获取是否可以编辑
setEnabled(enabled:bool) -> None # 设置是否可用
isEnabled() -> bool # 获取是否可用
setFlags(flags:Qt.ItemFlag) -> None # 设置标识
setSelectable(selectable:bool) -> None # 获取是否可选
isSelectable() -> bool # 获取是否可选
isUserTristate() -> bool # 获取是否用户有第三种状态
setIcon(icon:QIcon) -> None # 设置图标
setFont(font:QFont) -> None # 设置字体
setText(text:str) -> None # 设置文本
text() -> str # 获取文本
setToolTip(toolTip:str) -> None # 设置提示信息
setWhatsThis(whatsThis:str) -> None # 设置按Shift+F1键的提示信息
sortChildren(column:int, order:Qt.SortOrder=Qt.AscendingOrder) -> None # 对列进行排序
6.3 表格视图
表格视图控件 QTableView 可以用多行多列的单元格来显示标准数据模型,也可显示其他类型的数据模型。
用 QTableView 创建的表格视图控件的方法如下所示:
QTableView(parent:QWidget=None)
QTableView 类常用方法如下所示:
# 实例方法
rowAt(y:int) -> int # 获取y坐标位置处的行号
columnAt(x:int) -> int # 获取x坐标位置处的列号
rowViewportPosition(row:int) -> int # 获取行号对应的视图位置
columnViewportPosition(column:int) -> int # 获取列号对应的视图位置
setRowHidden(row:int, hide:bool) -> None # 设置是否隐藏行
setColumnHidden(column:int, hide:bool) -> None # 设置是否隐藏列
isRowHidden(row:int) -> bool # 获取指定行是否隐藏
isColumnHidden(column:int) -> bool # 获取指定列是否隐藏
showGrid() -> bool # 获取表格线条是否显示
setGridStyle(style:Qt.PenStyle) -> None # 设置表格线的样式
setRowHeight(row:int, height:int) -> None # 设置行的高度
rowHeight(row:int) -> int # 获取行的高度
setColumnWidth(column:int, width:int) -> None # 设置列的宽度
columnWidth(column:int) -> int # 获取列的宽度
setCornerButtonEnabled(enable:bool) -> None # 设置是否激活右下角按钮
isCornerButtonEnabled() -> bool # 获取右下角按钮是否激活
setHorizontalHeader(header:QHeaderView) -> None # 设置水平表头
horizontalHeader() -> QHeaderView # 获取水平表头
setVerticalHeader(header:QHeaderView) -> None # 设置垂直表头
verticalHeader() -> QHeaderView # 获取垂直表头
setSpan(row:int, column:int, rowSpan:int, columnSpan:int) -> None # 设置单元格的行跨度和列跨度
rowSpan(row:int, column:int) -> int # 获取单元格的行跨度
columnSpan(row:int, column:int) -> int # 获取单元格的列跨度
clearSpans() -> None # 清除单元格的行跨度和列跨度
setWordWrap(on:bool) -> None # 设置是否自动换行
setSortingEnabled(enable:bool) -> None # 设置是否启用排序
isSortingEnabled() -> bool # 获取是否启用排序
# 槽函数
resizeRowToContents(row:int) -> None # 自动调整指定行的高度
resizeRowsToContents() -> None # 自动调整所有行的高度
resizeColumnToContents(column:int) -> None # 自动调整指定列的宽度
resizeColumnsToContents() -> None # 自动调整所有列的宽度
selectRow(row:int) -> None # 选择行
selectColumn(column:int) -> None # 选择列
hideRow(row:int) -> None # 隐藏行
hideColumn(column:int) -> None # 隐藏列
showRow(row:int) -> None # 显示行
showColumn(column:int) -> None # 显示列
setShowGrid(show:bool) -> None # 设置是否显示网格
sortByColumn(column:int, order:Qt.SortOrder)-> None # 按列进行排序
用 setShowGrid(bool)
方法设置是否显示表格线条,用 setGridStyle(Qt.PenStyle)
方法可以设置表格线条的样式,其中参数 Qt.PenStyle 可取值如下:
Qt.PenStyle.NoPen # 没有表格线条
Qt.PenStyle.SolidLine
Qt.PenStyle.DashLine
Qt.PenStyle.DotLine
Qt.PenStyle.DashDotLine
Qt.PenStyle.DashDotDotLine
Qt.PenStyle.CustomDashLine # 用setDashPattern()方法自定义
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtWidgets import QTableView
from PySide6.QtGui import QStandardItemModel, QStandardItem
from PySide6.QtCore import Qt
class MyWidget(QWidget):
def __init__(self):
# 1.调用父类Qwidget类的__init__()方法
super().__init__()
# 2.调用setupUi()方法初始化页面
self.setup_ui()
def setup_ui(self):
# 1.设置窗口对象大小
self.resize(700, 500)
# 2.创建标准模型对象
model = QStandardItemModel()
# 3.设置表格的行数
model.setRowCount(3)
# 4.设置表格的列数
model.setColumnCount(4)
# 5.设置表格的水平表头
model.setHorizontalHeaderLabels(["部门", "姓名", "性别", "年龄"])
# 6.设置表格的垂直表头
model.setVerticalHeaderLabels(["1", "2", "3"])
department_list = ["魔法部", "超能力部"]
person_list = [
{"department": department_list[0], "name": "木之本樱", "gender": "女", "age": 10},
{"department": department_list[0], "name": "夏娜", "gender": "女", "age": 15},
{"department": department_list[1], "name": "御坂美琴", "gender": "女", "age": 14},
]
for i in range(0, len(person_list)):
j = 0
for key, value in person_list[i].items():
item = QStandardItem(str(value))
# 7.设置单元格的内容
model.setItem(i, j, item)
j += 1
# 8.创建表格视图
tableView = QTableView(self)
tableView.resize(700, 500)
# 9.设置要显示的数据模型
tableView.setModel(model)
# 10.设置表格列的宽度跟随内容改变
tableView.resizeColumnsToContents()
# 11.设置表格行的高度跟随内容改变
tableView.resizeRowsToContents()
# 12.设置单元格是否可以编辑
tableView.setEditTriggers(QTableView.EditTrigger.DoubleClicked)
# 13.设置表格颜色交错显示
tableView.setAlternatingRowColors(True)
# 14.设置选中模式
tableView.setSelectionMode(QTableView.SelectionMode.ExtendedSelection)
# 15.设置表格的选择行为
tableView.setSelectionBehavior(QTableView.SelectionBehavior.SelectItems)
# 16.设置是否自动换行
tableView.setWordWrap(True)
# 17.设置是否显示网格
tableView.setShowGrid(True)
# 18.合并单元格
tableView.setSpan(0, 0, 2, 1)
# 19.设置单击头部时是否可以排序
tableView.setSortingEnabled(True)
# 20.设置是否显示垂直滚动条
tableView.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
# 21.设置是否显示水平滚动条
tableView.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
# 22.定义信号与槽的连接
tableView.clicked.connect(self.clicked)
tableView.doubleClicked.connect(self.doubleClicked)
tableView.pressed.connect(self.pressed)
def clicked(self, index):
print(f"【{index.data()}】单元格被单击了")
def doubleClicked(self, index):
print(f"【{index.data()}】单元格被双击了")
def pressed(self, index):
print(f"【{index.data()}】单元格被按下了")
if __name__ == "__main__":
# 1.创建一个QApplication类的实例
app = QApplication(sys.argv)
# 2.创建一个窗口
window = MyWidget()
# 3.展示窗口
window.show()
# 4.进入程序的主循环并通过exit()函数确保主循环安全结束
sys.exit(app.exec())
7 选择模型
在列表、树和表格视图中,如要对数据项进行操作,需要先选中数据项,被选中的数据项高亮或反色显示。在 PySide6 中被选中的数据项记录在选择模型 QItemSelectionModel 中,如果多个视图控件同时关联到一个数据模型,选择模型可以记录多个视图控件中被选中的数据项,形成数据选择集 QItemSelection。视图控件有自己默认的选择模型,一般可以满足用户的需要;另外可以单独创建新的选择模型,以实现特殊目的。
视图控件都有 setSelectionModel(QItemSelectionModel)
方法和 selectionModel()
方法,用于设置视图控件的选择模型和获取选择模型。用 selectionModel()
方法获取某一个视图控件的选择模型后,可以使用 setSelectionModel()
方法提供给其他视图共享选择模型,因此一般没有必要新建选择模型。
用 QItemSelectionModel 创建选择模型的方法如下:
QItemSelectionModel(model:QAbstractItemModel=None)
QItemSelectionModel(model:QAbstractItemModel, parent:QObject)
QItemSelectionModel 类常用方法如下:
# 实例方法
clear() -> None # 清空选择模型并发送selectionChanged()和currentChanged()信号
reset() -> None # 清空选择模型,不发送信号
clearCurrentIndex() -> None # 清空当前选中项索引模型,并发送currentChanged()信号
setCurrentIndex(index:QModelIndex, command:QItemSelectionCommand.SelectionFlags) -> None # 设置当前项,并发送currentChanged()信号
select(index:QModelIndex, command:QItemSelectionCommand.SelectionFlags) -> None # 选择项,并发送selectionChanged()信号
select(selection:QItemSelection, command:QItemSelectionCommand.SelectionFlags) -> None # 选择项,并发送selectionChanged()信号
rowIntersectsSelection(row:int, parent:QModelIndex=QModelIndex()) -> bool # 如果选择的数据项与parent的子数据项的指定行有交集,则返回True
columnIntersectsSelection(column:int, parent:QModelIndex=QModelIndex()) -> bool # 如果选择的数据项与parent的子数据项的指定列有交集,则返回True
currentIndex() -> QModelIndex # 返回当前选中项的索引模型
hasSelection() -> bool # 如果有选择项,则返回True
isRowSelected(row:int, parent:QModelIndex=QModelIndex()) -> bool # 获取parent下的某行是否全部选中
isColumnSelected(column:int, parent:QModelIndex=QModelIndex()) -> bool # 获取parent下的某列是否全部选中
isSelected(index:QModelIndex) -> bool # 获取index数据项是否选中
selectedRows(column:int=0) -> List[int] # 获取某行中被选中数据项的索引列表
selectedColumns(row:int=0) -> List[int] # 获取某列中被选中数据项的索引列表
selectedIndexes() -> List[int] # 获取被选中数据项的索引列表
selection() -> QItemSelection # 获取项的选择集
setModel(model:QAbstractItemModel) -> None # 设置数据模型
# 槽函数
clearSelection() -> None # 清空选择模型,并发送currentChanged()信号
其中用 selection()
方法可以获取项的选择集 QItemSelection;用 select(index:QModelIndex,command:QItemSelectionModel.SelectionFlag)
方法可以往选择集中添加内容,或从选择集中移除选择,其中 command 是 QItemSelectionModel.SelectionFlag 的枚举值,可取的值如下所示。
QItemSelectionModel.SelectionFlag.NoUpdate # 选择集没有变化
QItemSelectionModel.SelectionFlag.Clear # 清空选择集
QItemSelectionModel.SelectionFlag.Select # 选择所有指定项
QItemSelectionModel.SelectionFlag.Deselect # 取消选择所有指定项
QItemSelectionModel.SelectionFlag.Toggle # 根据项的状态选择或不选择
QItemSelectionModel.SelectionFlag.Current # 更新当前的选择
QItemSelectionModel.SelectionFlag.Rows # 选择整行
QItemSelectionModel.SelectionFlag.Columns # 选择整列
QItemSelectionModel.SelectionFlag.SelectCurrent # Select | Current
QItemSelectionModel.SelectionFlag.ToggleCurrent # Toggle | Current
QItemSelectionModel.SelectionFlag.ClearAndSelect # Claer | Select
QItemSelectionModel 类常用信号如下:
currentChanged(current:QModelIndex, previous:QModelIndex) # 当前数据项发生改变时发射信号
currentRowChanged(current:QModelIndex, previous:QModelIndex) # 当前数据项的行改变时发射信号
currentColumnChanged(current:QModelIndex, previous:QModelIndex) # 当前数据项的列改变时发射信号
modelChanged(model:QAbstractItemModel) # 数据模型发生改变时发射信号
selectionChanged(selected:QItemSelection, deselected:QItemSelection) # 选择区域发生改变时发射信号
选择集 QItemSelection 是指数据模型中已经被选中的项的集合,其方法下所示。
select(topLeft:QModelIndex, bottomRight:QModelIndex) -> None # 添加左上角到右下角位置处的所有项
merge(other:QItemSelection, command:QItemSelectionModel.SelectionFlag) -> None # 与其它选择集合并
indexes() -> List[QModelIndex] # 返回选择集中的所有索引
contains(index:QModelIndex) -> bool # 获取指定的项是否在选择集中
clear() -> None # 清空选择集
count() -> int
8.代理控件
在视图控件中双击某个数据项,可以修改数据项当前显示的值,即可以输入新的值。输入新值时,并不是直接在视图控件上输入(视图控件只具有显示数据的功能),而是在视图控件的单元格位置出现一个新的可以输入数据的控件,例如 QLineEdit。QLineEdit 读取数据项的值作为初始值,供用户修改,修改完成后通过数据项的索引把数据保存到数据模型中,并通知视图控件显示新的数据,像这种为视图控件提供编辑功能的控件称为代理控件或委托控件。
系统为每种数据类型定义了默认的代理控件,用户也可以自定义代理控件。定义代理控件需要用 QStyledItemDelegate 类或 QItemDelegate 类创建子类,这两个类都继承自 QAbstractItemDelegate 类。这两个类的主要区别是前者可以使用当前的样式表来设置代理控件的样式,因此建议使用前者来定义代理控件。
在 QStyledItemDelegate 或 QItemDelegate 的子类中定义代理控件的类型、位置,以及如何读取和返回数据。视图控件都有从 QAbstractItemView 继承而来的 setItemDelegate(delegate:QAbstractItemDelegate)
方法、 setItemDelegateForColumn(column:int,delegate:QAbstractItemDelegate)
方法和 setItemDelegateForRow(row:int,delegate:QAbstractItemDelegate)
方法,可以分别为所有的数据项、列数据项和行数据项设置代理控件。创建代理控件可以用项编辑器工厂 QItemEditorFactory 定义默认的代理控件,也可以自定义代理控件的类型。
自定义代理控件需要重写 QStyledItemDelegate 类或 QItemDelegate 类的下面 4 个函数:
# 用于创建代理控件的实例对象并返回该实例对象
createEditor(parent:QWidget,option:QStyleOptionViewItem,index:QModelIndex) -> QWidget
# 用于读取视图控件的数据项的值到代理控件中
setEditorData(editor:QWidget,index:QModelIndex) -> None
# 用于将编辑后的代理控件的值返回到数据模型中
setModelData(editor:QWidget,model:QAbstractItemModel,index:QModelIndex) -> None
# 用于设置代理控件显示的位置
updateEditorGeometry(editor:QWidget,option:QStyleOptionViewItem,index:QModelIndex) -> None
createEditor()
函数中的参数 parent 指代理控件所在的窗口,通常取视图控件所在的窗体;其他 3 个函数的 editor 指 createEditor() 返回的代理控件,用于传递数据;QModelIndex 是数据项的索引,系统会给实参传递索引; QStyleOptionViewItem 传递的一些属性用于确定代理控件的位置和外观,其属性如下所示。
QStyleOptionViewItemcol 的属性 | 属性值的类型 | 说明 |
---|---|---|
backgroundBrush | QBursh | 项的背景画刷 |
checkState | Qt.CheckState | 项的勾选状态 |
decorationAlignment | Qt.Alignment | 项的图标对齐位置 |
decorationPosition | QStyleOptionViewItem.Postion | 项的图标位置 |
decorationSize | QSize | 项的图标尺寸 |
displayAlignment | Qt.Alignment | 项的文字对齐方式 |
features | QStyleOptionViewItem.ViewItemFeatures | 项所具有的特征 |
font | QFont | 项的字体 |
icon | QIcon | 项的图标 |
index | QModelIndex | 项的模型索引 |
showDecorationSelected | bool | 项是否显示图标 |
text | QString | 项显示的文本 |
textElideMode | Qt.TextElideMode | 省略号的模式 |
viewItemPosition | QStyleOptonViewItem.ViewItemPosition | 项在行中的位置 |
direction | Qt.LayoutDirection | 布局方向 |
palette | QPalette | 调色板 |
rect | QRect | 项的矩形区域 |
styleObject | QObject | 项的窗口类型 |
version | int | 版本 |
其中枚举值 QStyleOptionViewItem.Position 可取值如下:
QStyleOptionViewItem.Position.Left
QStyleOptionViewItem.Position.Right
QStyleOptionViewItem.Position.Top
QStyleOptionViewItem.Position.Bottom
枚举值 QStyleOptionViewItem.ViewItemFeatures 可取值如下:
QStyleOptionViewItem.ViewItemFeatures.None
QStyleOptionViewItem.ViewItemFeatures.WrapText
QStyleOptionViewItem.ViewItemFeatures.Alternate
QStyleOptionViewItem.ViewItemFeatures.HasCheckIndicator
QStyleOptionViewItem.ViewItemFeatures.HasDisplay
QStyleOptionViewItem.ViewItemFeatures.HasDecoration
枚举值 QStyleOptionViewItem.ViewItemPosition 可取值如下:
QStyleOptionViewItem.ViewItemPosition.Beginning
QStyleOptionViewItem.ViewItemPosition.Middle
QStyleOptionViewItem.ViewItemPosition.End
QStyleOptionViewItem.ViewItemPosition.OnlyOne # 行中只有一个项,两端对齐
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtWidgets import QTableView
from PySide6.QtWidgets import QStyledItemDelegate
from PySide6.QtWidgets import QComboBox, QSpinBox
from PySide6.QtGui import QStandardItemModel, QStandardItem, Qt
class ComboBoxDelegate(QStyledItemDelegate):
def createEditor(self, parent, option, index):
# 创建下拉组合控件并返回
comboBox = QComboBox(parent)
comboBox.addItems(["男", "女"])
return comboBox
def setEditorData(self, editor, index):
# 将模型中的数据设置到编辑器中
data = index.data()
editor.setCurrentText(data)
def setModelData(self, editor, model, index) -> None:
# 将编辑器中的数据更新回模型
value = editor.currentText()
model.setData(index, value, Qt.ItemDataRole.EditRole)
def updateEditorGeometry(self, editor, option, index) -> None:
# 更新编辑器的几何布局
editor.setGeometry(option.rect)
class SpinBoxDelegate(QStyledItemDelegate):
def createEditor(self, parent, option, index):
# 创建数字选择控件并返回
spinBox = QSpinBox(parent)
spinBox.setRange(0, 300)
return spinBox
def setEditorData(self, editor, index):
# 将模型中的数据设置到编辑器中
value = index.data()
editor.setValue(int(value))
def setModelData(self, editor, model, index) -> None:
# 将编辑器中的数据更新回模型
value = editor.value()
model.setData(index, value, Qt.ItemDataRole.EditRole)
def updateEditorGeometry(self, editor, option, index) -> None:
# 更新编辑器的几何布局
editor.setGeometry(option.rect)
class MyWidget(QWidget):
def __init__(self):
# 1.调用父类Qwidget类的__init__()方法
super().__init__()
# 2.调用setupUi()方法初始化页面
self.setup_ui()
def setup_ui(self):
# 1.设置窗口对象大小
self.resize(700, 500)
# 2.创建标准模型对象
model = QStandardItemModel()
# 3.设置表格的行数
model.setRowCount(3)
# 4.设置表格的列数
model.setColumnCount(4)
# 5.设置表格的水平表头
model.setHorizontalHeaderLabels(["部门", "姓名", "性别", "年龄"])
# 6.设置表格的垂直表头
model.setVerticalHeaderLabels(["1", "2", "3"])
department_list = ["魔法部", "超能力部"]
person_list = [
{"department": department_list[0], "name": "木之本樱", "gender": "女", "age": 10},
{"department": department_list[0], "name": "夏娜", "gender": "女", "age": 15},
{"department": department_list[1], "name": "御坂美琴", "gender": "女", "age": 14},
]
for i in range(0, len(person_list)):
j = 0
for key, value in person_list[i].items():
item = QStandardItem(str(value))
# 7.设置单元格的内容
model.setItem(i, j, item)
j += 1
# 8.创建表格视图
tableView = QTableView(self)
tableView.resize(700, 500)
# 9.设置要显示的数据模型
tableView.setModel(model)
# 10.设置单元格是否可以编辑
tableView.setEditTriggers(QTableView.EditTrigger.DoubleClicked)
# 11.设置表格颜色交错显示
tableView.setAlternatingRowColors(True)
# 12.设置选中模式
tableView.setSelectionMode(QTableView.SelectionMode.ExtendedSelection)
# 13.设置表格的选择行为
tableView.setSelectionBehavior(QTableView.SelectionBehavior.SelectItems)
# 14.设置是否自动换行
tableView.setWordWrap(True)
# 15.设置是否显示网格
tableView.setShowGrid(True)
# 16.设置单击头部时是否可以排序
tableView.setSortingEnabled(True)
# 17.设置是否显示垂直滚动条
tableView.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
# 18.设置是否显示水平滚动条
tableView.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
# 19.只对第三列(性别)应用代理
delegate_gril = ComboBoxDelegate(tableView)
tableView.setItemDelegateForColumn(2, delegate_gril)
# 20.只对第四列(年龄)应用代理
delegate_age = SpinBoxDelegate(tableView)
tableView.setItemDelegateForColumn(3, delegate_age)
if __name__ == "__main__":
# 1.创建一个QApplication类的实例
app = QApplication(sys.argv)
# 2.创建一个窗口
window = MyWidget()
# 3.展示窗口
window.show()
# 4.进入程序的主循环并通过exit()函数确保主循环安全结束
sys.exit(app.exec())
本文来自博客园,作者:Yasuo_Hasaki,转载请注明原文链接:https://www.cnblogs.com/hasaki-yasuo/p/18827061