列表、表格、树
基于项的控件有
- 列表控件 QListWidget
- 表格控件 QTaleWidget
- 树结构控件 QTreeWidget
它们是从基于模型的控件继承而来的,基于模型的控件有 QListView、QTableView和QTreeView,这些控件之间的继承关系如图所示。本处只对这三个控件做使用说明。更高级部分请参考进阶篇中Model/View章节下的更多高级用法。
列表控件QListWidget及其项QListWidgetItem
QListWidget 是一个用于显示列表的类,可以添加和删除列表中的每个项目。
项目(Item)是组成列表的基本单位,每个项目都是 QListWidgetItem 类的实例。
QListWidget包含内部模型,并通过内部模型管理QListWidgetItem。QListWidget 适用于显示简单的列表,如果想要更强大的列表显示功能,则使用QListView。QListView 可以使用自定义模型,而OListWidget 只能使用内部模型。
从继承结构图图中可以看出,QListWidget 是 QListView的子类,可以看作OListView的简单化操作子类,集成了内部模型,并通过OListWidgetItem来管理项目。
QListWidget 是传统意义上的基于项目的列表显示,下面会重点介绍它的项目OListWidgetItem。
实例化
列表控件QListWidget 由一列多行构成,每行称为一个项(item),每个项是一个QListWidgetItem对象。
可以继承 QListWidgetItem 创建用户自定义的项;也可以先创建QWidget实例,在其上添加一些控件,然后把QWidget 放到 QListWidgetItem 的位置形成复杂的列表控件。
列表控件QListWidget是从QListView 类继承而来的用QListWidget 类创建列表控件的方法如下所示,其中parent是QListWidget列表控件所在的父窗口或控件。
用QListWidgetItem创建列表项的方法如下所示其中type可取QListWidgetItemType(值为0)或QListWidgetItem.UserType(值为1000),前者是默认值,后者是用户自定义类型的最小值。可以用QListWidgetItem类创建子类定义新的类型。
from PySide6.QtWidgets import QListWidget,QListWidgetItem
QListWidget(parent: Union[PySide6.QtWidgets.QWidget,NoneType]= None)-> None
QListWidgetItem(icon: Union[PySide6.QtGui.QIcon,PySide6.QtGui.QPixmap],text: str,listview: Union[PySide6.QtWidgets.QListWidget,NoneType]= None,type: int = < ItemType.Type: 0 >)-> None
QListWidgetItem(listview: Union[PySide6.QtWidgets.QListWidget,NoneType]= None,type: int = < ItemType.Type: 0 >)-> None
QListWidgetItem(Other: PySide6.QtWidgets.QListWidgetItem)-> None
QListWidgetItem(text: str,listview: Union[PySide6.QtWidgets.QListWidget,NoneType]= None,type: int = < ItemType.Type: 0 >)-> None
列表控件QListWidget 的常用方法
列表控件QListWidget的常用方法如表所示主要方法介绍如下
-
插入、新增、统计项
-
用addItem(item: QListWidgetItem)方法可以在列表控件的末尾添加已经存在的项;
-
用addItem(label: str)方法可以用文本创建一个新项,并添加到列表控件的末尾;
-
用addItems(labels;Sequence[str])方法可以用文本列表添加多个项;
-
用insertItem(row: int,item: QListWidgetItem)方法insertItem(row: int,label: str)方法和insertItems(row: int,labels:Sequence[str])方法可以在指定的行插人项;
-
用count()方法可以获得项的数量,包括隐藏的项。
-
-
设置项、获取项
-
用setCurrentItem(QListWidgetItem)方法可以把指定的项设置成当前的项,
-
用setCurrentRow(int)方法将指定行的项设置成当前项;
-
用currentItem()方法获取当前的项;
-
用currentRow()方法获取当前项所在的行;
-
用rowQListWidgetItem)方法获取项所在的行号。
-
-
获取项信息
- 用item(row:int)方法可以获取指定行上的项(行的编号从0开始);
- 用itemAt(QPoint)方法或itemAt(x:int,y:int)方法可以获取指定位置的项
- 用visualItemRect(QListWidgetItem)方法可以获取项所占据的区域 QRect。
-
移除项
- 用takeItem(row:int)方法从列表中移除指定行上的项,并返回该项;
- 用clear()方法清空所有的项.
-
项排序
- 用setSortingEnabled(bool)方法设置是否可以进行排序;
- 用sortItems(order=Qt.AscendingOrder)方法设置排序方法,其中 order 可取 Qt.AscendingOrder(升序)或Qt.DescendingOrder(降序)。
-
项放置到控件
- 用setItemWidget(QListWidgetItem,QWidget)方法可以把一个控件放到项的位置,例如在一个 QWidget 上放置控件布局,然后把QWidget 对象放到项的位置形成复杂的项;
- 用removeItemWidget(QListWidgetItem)方法可以移除项上的控件用itemWidget(QListWidgetItem)方法可以获取项的控件。
-
查找项
- 用findItems(text;str,flags;Qt.MatchFlags)方法可以查找满足匹配规则的项List[QListWidgetItem],其中参数flags 可取:
- Qt.MatchExactly
- Qt.MatchFixedString
- Qt.MatchContains
- Qt.MatchStartsWith
- Qt.MatchEndsWith
- Qt.MatchCaseSensitive
- Qt.MatchRegularExpression
- Qt.MatchWildcard
- Qt.MatchWrap
- Qt.MatchRecursive
- 用findItems(text;str,flags;Qt.MatchFlags)方法可以查找满足匹配规则的项List[QListWidgetItem],其中参数flags 可取:
-
用setModel(model: QAbstractItemModel)方法和 setSelectionModel(QItemSelectionModel)方法可分别设置数据模型和选择模型关于数据模型和选择模型见后续内容。
-
用supportedDropActions()方法获取支持的拖放动作QtDropAction,其中Qt.DropAction 可以取:
- Qt.CopyAction(复制)
- Qt.MoveAction(移动)
- Qt.LinkAction(链接)
- Qt.IgnoreAction(什么都不做)
- Qt.TargetMoveAction(目标对象接管)
QListWidget的方法及参数类型 | 说明 |
---|---|
addItem(item: QListWidgetItem) | 在列表控件中添加项 |
addItem(label: str) | 用文本创建项并添加项 |
addItems(labels: Sequence[str]) | 用文本列表添加多个项 |
insertItem(row: int,item: QListWidgetItem) | 在列表中插人项 |
insertItem(row:int,label: str) | 用文本创建项并插人项 |
insertItems(row: int,labels: Sequence[str]) | 用文本列表创建项并插入多个项 |
setCurrentItem(QListWidgetItem) | 设置当前项 |
currentItem() | 获取当前项QListWidgetItem |
count() | 获取列表控件中项的数量 |
takeItem(row:int) | 移除指定索引值的项,并返回该项 |
[slot]clear() | 清空所有项 |
openPersistentEditor(QListWidgetItem) | 打开指定项的编辑框,用于编辑文本 |
isPersistentEditorOpen(QListWidgetltem) | 获取编辑框是否已打开 |
closePersistentEditor(QListWidgetltem) | 关闭编辑框 |
currentRow() | 获取当前行的索引号 |
item(row:int) | 获取指定行的项 |
itemAt(QPoint) | 获取指定位置处的项 |
itemAt(x;int,y:int) | 获取指定位置处的项 |
itemFromIndex(QModelIndex) | 获取指定模型索引QModelIndex的项 |
indexFromItem(QListWidgetItem) | 获取指定项的模型索引QModelIndex |
setItemWidget(QListWidgetItem,QWidget) | 把某控件显示在指定项的位置处 |
removeItemWidget(QListWidgetItem) | 移除指定项上的控件 |
itemWidget(QListWidgetItem) | 获取指定项的位置处的控件 |
findItems(text: str,flags: Qt.MatchFlags) | 查找满足匹配规则的项List[QListWidgetItem] |
[slot]scrollToItem(QListWidgetItem) | 滚动到指定的项,使其可见 |
selectedItems() | 获取选中项的列表 List[QListWidgetItem] |
setCurrentRow(int) | 指定行的项为当前项 |
row(QListWidgetItem) | 获取指定项所在的行号 |
visualItemRect(item: QListWidgetItem) | 获取项所占据的区域QRect |
setSortingEnabled(bool) | 设置是否可以进行排序 |
isSortingEnabled() | 获取是否可以排序 |
sortItems(order=Qt.AscendingOrder) | 按照排序方式进行项的排序 |
supportedDropActions() | 获取支持的拖放动作 Qt.DropAction |
setModel(model:QAbstractItemModel) | 设置数据模型 |
setSelectionModel(QItemSelectionModel) | 设置选择模型 |
clearSelection() | 清除选择 |
setAlternatingRowColors(enable:bool) | 设置交替色 |
mimeData(items:Sequence[QListWidgetItem]) | 获取多个项的 mime数据 QMimeData |
mimeTypes() | 获取mime数据的类型List[str] |
列表控件QListWidget 的信号
列表控件QListWidget 的信号如表所示
QListWidget的信号及参数类型 | 说明 |
---|---|
currentItemChanged(currentItem,previousltem) | 当前项发生改变时发送信号 |
currentRowChanged(currentRow) | 当前行发生改变时发送信号 |
currentTextChanged(currentText) | 当前项的文本发生改变时发送信号 |
itemActivated(QListWidgetItem) | 单击或双击项,使其变成活跃项时发送信号 |
itemChanged(QListWidgetltem) | 项的数据发生改变时发送信号 |
itemClicked(QListWidgetItem) | 单击某个项时发送信号 |
itemDoubleClicked(QListWidgetItem) | 双击某个项时发送信号 |
item Entered(QListWidgetItem) | 光标进人某个项时发送信号 |
itemPressed(QListWidgetltem) | 当鼠标在某个项上按下按键时发送信号 |
itemSelectionChanged() | 项的选择状态发生改变时发送信号 |
列表项QListWidgetItem
QListWidgetItem类提供了一个与QListWidget项视图类一起使用的项。
from PySide6.QtWidgets import QListWidgetItem
QListWidgetItem(icon: Union[PySide6.QtGui.QIcon, PySide6.QtGui.QPixmap], text: str, listview: Union[PySide6.QtWidgets.QListWidget, NoneType] = None, type: int = < ItemType.Type: 0 >)-> None
QListWidgetItem(listview: Union[PySide6.QtWidgets.QListWidget, NoneType] = None, type: int = < ItemType.Type: 0 >)-> None
QListWidgetItem(other: PySide6.QtWidgets.QListWidgetItem)-> None
QListWidgetItem(text: str, listview: Union[PySide6.QtWidgets.QListWidget, NoneType] = None, type: int = < ItemType.Type: 0 >)-> None
- listview – PySide6.QtWidgets.QListWidget
- other – PySide6.QtWidgets.QListWidgetItem
- type – int
- icon – PySide6.QtGui.QIcon
- text – str
构造具有给定父级的指定类型的空列表小部件项。如果未指定父项,则需要使用insertItem()将该项插入到列表小部件中。
此构造函数将项插入传递给构造函数的父级的模型中。如果对模型进行了排序,则插入的行为是不确定的,因为模型将对目前尚未构造的项调用"<"运算符方法。为了避免不确定的行为,我们建议不要指定父项,而是使用insertItem()。
构造一个具有给定图标、文本和父项的指定类型的空列表小部件项。如果未指定父项,则需要使用insertItem()将该项插入到列表小部件中。
此构造函数将项插入传递给构造函数的父级的模型中。如果对模型进行了排序,则插入的行为是不确定的,因为模型将对目前尚未构造的项调用"<"运算符方法。为了避免不确定的行为,我们建议不要指定父项,而是使用insertItem()。
构造其他的副本。请注意,type()和listWidget()不会被复制。
当重新实现clone()时,此函数非常有用。
使用给定的文本和父对象构造指定类型的空列表小部件项。如果未指定父项,则需要使用insertItem()将该项插入到列表小部件中。
此构造函数将项插入传递给构造函数的父级的模型中。如果对模型进行了排序,则插入的行为是不确定的,因为模型将对目前尚未构造的项调用"<"运算符方法。为了避免不确定的行为,我们建议不要指定父项,而是使用insertItem()。
列表项QListWidgetItem官方描述
QListWidgetItem表示QListWidget中的单个项目。每个项目可以包含多条信息,并将适当地显示这些信息。
项目视图便利类使用经典的基于项目的接口,而不是纯粹的模型/视图方法。对于更灵活的列表视图小部件,可以考虑将QListView类与标准模型一起使用。
通过指定列表小部件,列表项可以在构建时自动插入到列表中:
QListWidgetItem(tr("Hazel"), listWidget)
或者,也可以在没有父窗口小部件的情况下创建列表项,然后使用insertItem()将其插入到列表中。
列表项通常用于显示文本()和图标()。这些是用setText()和setIcon()函数设置的。文本的外观可以使用setFont()、setForeground()和setBackground(。列表项中的文本可以使用setTextAlignment()函数进行对齐。工具提示、状态提示和"这是什么?"帮助可以添加到带有setToolTip()、setStatusTip(()和setWhatsThis()的列表项中。
默认情况下,项目是启用的、可选择的、可检查的,并且可以是拖放操作的来源。
可以通过使用适当的值调用setFlags()来更改每个项目的标志(请参见ItemFlags)。可检查项可以使用setCheckState()函数进行检查、取消检查和部分检查。相应的checkState()函数指示项目的当前检查状态。
isHidden()函数可用于确定该项是否隐藏。要隐藏项目,请使用setHidden()。
子类别化
当对QListWidgetItem进行子类化以提供自定义项时,可以为它们定义新的类型,使它们能够与标准项区分开来。对于需要此功能的子类,请确保在构造函数中使用等于或大于UserType的新类型值调用基类构造函数。
列表项QListWidgetItem方法
- PySide6.QtWidgets.QListWidgetItem.ItemType
(继承enum.IntEnum)此枚举描述用于描述列表小部件项的类型。您可以在QListWidgetItem子类中定义新的用户类型,以确保对自定义项进行特殊处理。
Constant | Description |
---|---|
QListWidgetItem.Type | 列表小部件项目的默认类型。 |
QListWidgetItem.UserType | 自定义类型的最小值。UserType以下的值由Qt保留。 |
列表项QListWidgetItem的常用方法如表所示,主要方法介绍如下
-
用setText(str)方法和 setIcon(QIcon)方法可以分别设置项的文字和图标;用text()方法和 icon()方法可以分别获取项的文字和图标。
-
用setForeground(QColor)方法和 setBackground(QColor)方法可以设置前景色和背景色,其中参数 QColor 可以取:
- QBrush
- Qt.BrushStyle
- Qt.GlobalColor
- QGradientQImage
- QPixmap
-
用setSelected(bool)方法可以设置项是否处于选中状态,用isSelected()方法可以获取项是否处于选中状态。
-
用setCheckState(Qt.CheckState)方法设置项是否处于勾选状态,其中参数 QCheckState 可以取以下值,用checkState()方法获取项的选状态。:
- Qt.Unchecked(未勾选)
- Qt.PartiallyChecked(部分勾选如果有子项)
- QtChecked(勾选);
-
用setFlags(Qt.ItemFlags)方法设置项的标识其中参数 QtItemFlags可取的值如表所示。
例如setFlags(Qt.ItemIsEnabled Qt.ItemIsEditable)将使项处于可编辑状态,双击该项可以编辑项的文字。
Qt.ItemFlags 的取值 说明 Qt.ItemFlags的取值 说明 Qt.NoItemFlags 没有标识符 Qt.ItemIsUserCheckable 项可以勾选 Qt.ItemIsSelectable 项可选 Qt.ItemIsEnabled 项被激活 Qt.ItemIsEditable 项可编辑 Qt.ItemIsAutotristate 如有子项,则有第3种状态 Qt.ItemIsDragEnabled 项可以拖拽 Qt.ItemNeverHasChildren 项没有子项 Qt.ItemIsDropEnabled 项可以拖放 Qt.ItemlsUserTristate 可在3种状态之间循环切换 -
用setData(role:int, value:Any)方法可以设置项的某种角色的值,用data(role: int)方法可以获取某种角色的值
-
用write(QDataStream)方法可以把项对象写人到数据流 QDataStream 中,用read(QDataStream)方法从数据流中读取项,数据流可以直接保存到文件中。有关数据流的内容见流数据章节
方法 | 描述 |
---|---|
background()-> PySide6.QtGui.QBrush | 返回用于显示列表项背景的画笔。 |
checkState()-> PySide6.QtCore.Qt.CheckState | 返回列表项的选中状态(请参阅CheckState)。 |
clone()-> PySide6.QtWidgets.QListWidgetItem | 创建项目的精确副本。 |
data(role: int)-> Any | 返回给定角色的项目数据。如果您需要额外的角色或特定角色的特殊行为,请重新实现此功能。 |
flags()-> PySide6.QtCore.Qt.ItemFlag | 返回此项目的项目标志(请参阅项目标志)。 |
font()-> PySide6.QtGui.QFont | 返回用于显示此列表项的文本的字体。 |
foreground()-> PySide6.QtGui.QBrush | 返回用于显示列表项的前景(例如文本)的画笔。 |
icon()-> PySide6.QtGui.QIcon | 返回列表项的图标。 |
isHidden()-> bool | 如果项目是隐藏的,则返回true;否则返回false。 |
isSelected()-> bool | 如果选择了项目,则返回true;否则返回false。 |
listWidget()-> PySide6.QtWidgets.QListWidget | 返回包含该项目的列表小部件。 |
__lt__ | 如果此项目的文本小于其他项目的文本,则返回true;否则返回false。 |
read(in_: PySide6.QtCore.QDataStream)-> None | 从in的流中读取项目。 |
setBackground(brush: Union[PySide6.QtGui.QBrush, PySide6.QtCore.Qt.BrushStyle, PySide6.QtCore.Qt.GlobalColor, PySide6.QtGui.QColor, PySide6.QtGui.QGradient, PySide6.QtGui.QImage, PySide6.QtGui.QPixmap])-> None | 将列表项的背景笔刷设置为给定的笔刷。设置默认构造的笔刷将使视图使用样式中的默认颜色。 |
setCheckState(state: PySide6.QtCore.Qt.CheckState)-> None | 将列表项的检查状态设置为state。 |
setData(role: int, value: Any)-> None | 将给定角色的数据设置为给定值。如果您需要额外的角色或特定角色的特殊行为,请重新实现此功能。 |
setFlags(flags: PySide6.QtCore.Qt.ItemFlag)-> None | 将列表项的项标志设置为标志。 |
setFont(font: Union[PySide6.QtGui.QFont, str, Sequence[str]])-> None | 将绘制项目时使用的字体设置为给定的字体。 |
setForeground(brush: Union[PySide6.QtGui.QBrush, PySide6.QtCore.Qt.BrushStyle, PySide6.QtCore.Qt.GlobalColor, PySide6.QtGui.QColor, PySide6.QtGui.QGradient, PySide6.QtGui.QImage, PySide6.QtGui.QPixmap])-> None | 将列表项的前景笔刷设置为给定的笔刷。设置默认构造的笔刷将使视图使用样式中的默认颜色。 |
setHidden(hide: bool) | 如果隐藏为真,则隐藏项目;否则显示项目。 |
setIcon(icon: Union[PySide6.QtGui.QIcon, PySide6.QtGui.QPixmap])-> None | 将列表项的图标设置为给定的图标。 |
setSelected(select: bool)-> None | 设置要选择的项目的选定状态。 |
setSizeHint(size: PySide6.QtCore.QSize)-> None | 将列表项的大小提示设置为大小。如果未设置大小提示或大小无效,则项目委托将根据项目数据计算大小提示。 |
setStatusTip(statusTip: str)-> None | 将列表项的状态提示设置为statusTip指定的文本。QListWidget鼠标跟踪需要启用才能使此功能正常工作。 |
setText(text: str)-> None | 将列表项的状态提示设置为statusTip指定的文本。QListWidget鼠标跟踪需要启用才能使此功能正常工作。 |
setTextAlignment(alignment: PySide6.QtCore.Qt.AlignmentFlag)-> None setTextAlignment(alignment: PySide6.QtCore.Qt.AlignmentFlag)-> None setTextAlignment(alignment: int)-> None | 将列表小部件项的文本设置为给定的文本。 将列表项的文本对齐方式设置为对齐方式。使用采用Alignment参数的重载。将列表项的文本对齐方式设置为对齐方式。 |
setToolTip(toolTip: str)-> None | 将列表项的工具提示设置为工具提示指定的文本。 |
setWhatsThis(whatsThis: str)-> None | 将列表项的"What’s This?"帮助设置为whatsThis指定的文本。 |
sizeHint()-> PySide6.QtCore.QSize | 返回为列表项设置的大小提示。 |
statusTip()-> str | 返回列表项的状态提示。 |
text()-> str | 返回列表项的文本。 |
textAlignment()-> int | 返回列表项的文本对齐方式。 |
toolTip()-> str | 返回列表项的工具提示。 |
type()-> int | 返回传递给QListWidgetItem构造函数的类型。 |
whatsThis()-> str | 返回列表项的"这是什么?"帮助文本。 |
write(out: PySide6.QtCore.QDataStream)-> None | 写入要流式输出的项。 |
增/删项目
可以使用以下两种方法将项目添加到列表中:一是使用 QListWidget.addtem0函数将子项增加到列表中,二是在实例化 QListWidgetItem 时传递父类创建项目。以下方法的效果是一样的:
listwidget = QListwidget()
listWidget.addItem('iteml')
listwidget.addItem(QListwidgetItem('item2'))
QListwidgetItem('item3',listwidget)
如果需要在列表的特定位置插入一个新项目,则应该使用 QListWidget.insertItem(rowitem)函数。使用QListWidgetItem(item3listWidget)函数只能添加到末尾,因此这时不能使用这种方法。以下方法的效果是一样的:
listWidget.insertItem(2,'item insert
listwidget.insertItem(2,QListwidgetItem('item insert'))
使用QListWidgettakeItem(row)函数可以删除项目,使用count0函数可以查询项目的总数。
选择
需要先弄清楚两个概念,即select 和 check。
- select 是基于QListWidget 的
- check 是基于 QListWidgetItem 的。
select 和 check 的定位不同,select 是选取多个项目的概念;check 是单个项目是否被选中的概念,其左侧有一个复选框标志。需要注意的是,select的选择和 check 的选中两者是独立的,是两套体系。
select 包含函数 selectionMode()和 selectionBehavior(),check 包含 checkState0函数。此外,也离不开QListWidgetItem.flag()函数,因为它决定了用户能否对项目进行选择编辑及交互等。
QListWidget.selectionMode()函数决定了在列表中可以同时选择多少个项目,以及是否可以创建复杂的项目选择,这可以通过 setSelectionMode()函数进行设置。setSelectionMode0函数支持的参数如表所示,其中最常用的参数是 SingleSelection和 ExtendedSelection。
参数QAbstractltemView | 值 | 描 述 |
---|---|---|
SingleSelection | 1 | 当用户选择一个项目时,任何已选择的项目都将变为未选择状 态。 用户可以通过在单击所选项目时按Ctrl键来取消所选项目 |
ContiguousSelection | 4 | 当用户以通常的方式选择一个项目时,选择被清除并被重新选 中。 如果用户在单击项目的同时按下Shift键,则当前项目和单击 项目之间的所有项目都被选中或取消选中(取决于单击项目的状态)当用户以通常的方式选择一个项目时,选择被清除并被重新选 |
ExtendedSelection | 3 | 中。如果用户在单击某个项目时按下Ctrl键,则单击的项目被切 换且所有其他项目保持不变。 如果用户在单击项目时按下 Shin 键,则当前项目和单击项目之间的所有项目都被选中或被取消选 中(具体取决于单击项目的状态)。 可以通过使用鼠标拖到多个项 目上来选择它们 |
MultiSelection | 2 | 当用户以通常的方式选择一个项目时,该项目的选择状态会被 切换,而其他项目则保持不变。 可以通过使用鼠标拖到多个项目 上来切换它们 |
NoSelection | 0 | 无法选择项目 |
QListWidgetselectionBehavior()函数决定了用户的选择行为,同时决定用户选择单个项目、行还是列,可以通过 setSelectionBehavior0修改函数值。setSelectionBehavior()函数支持的参数如表所示
参 数 | 值 | 描 述 |
---|---|---|
QAbstractItemView.SelectItems | 0 | 选择单个项目 |
QAbstractItemView.SelectRows | 1 | 仅选择行 |
QAbstractItemView.SelectColumns | 2 | 仅选择列 |
QListWidgetItem.CheckState()函数决定了 item 的 check 状态,可以使用 setCheckState()函数修改该值。setCheckState0函数支持的参数如表所示。
参 数 | 值 | 描 述 |
---|---|---|
Qt.Unchecked | 0 | 该项目未选中 |
Qt.PartiallyChecked | 1 | 该项目己部分检查。如果检查了部分(但不是全部)子项,则分 层模型中的项可能会被部分检查 |
Qt.Checked | 2 | 该项目已检查 |
QListWidgetItemflags()函数决定了 item 是否可以被选择、编辑及交互等,可以使用setFlags()函数修改该值。setFlags0函数支持的参数如表所示。如果对项目设置了Qt.NoItemFlags,那么该项目将无法被选择(select)、编辑和拖动等
参数 数 | 鱼 | 档 述 |
---|---|---|
Qt.NoItemFlags | 0 | 没有设置任何属性 |
QL.ItemIsSclectable | 1 | 可以选择 |
QL.ItemIsEditable | 2 | 可以被编辑 |
Qt.ItemIsDragEnabled | 4 | 可以被拖动 |
QL.ItemIsDropEnabled | 8 | 可以用作放置目标 |
Qt.ItemIsUserCheckablc | 16 | 用户可以选中或取消选中 |
Qt.ItemIsEnabled | 32 | 用户可以与项目进行交互 |
Qt.ItemIsAutotristatc | 64 | 项目的状态取决于其子项的状态。可以自动管理QTreeWidget中父项 的状态(如果所有子项都被选中,则选中;如果所有子项都未被选中,则取消选中;如果只选中一些子项,则部分选中) |
QL.ItemNeverHasChildren | 128 | 该项目永远不会有子项目,仅用于优化目的 |
Qt.ItemIsUserTristate | 256 | 用户可以在3个不同的状态之间循环。这个值是在Qt5.5中添加的 |
外观
接下来使用常规操作修改项目的外观,以下都是 QListWidgetItem 的函数:
- 使用setText()函数和 setIcon()函数可以修改显示的文本和图片,
- 可以通过 setFont()函数、setForeground()函数和 setBackground()函数定义字体、前景色和背景色,
- 可以使用setTextAlignment()函数对齐列表项中的文本。
- 在默认情况下,项目是可用的(enabled)、可选择的(selectable)、可检查的(checkable),并且可以被拖放。使用 setHidden()函数可以隐藏项目
信号与槽
使用currentItem0函数可以获取列表中的当前项目,使用setCurrentItem0函数可以改变当前项目。用户还可以通过使用键盘导航或鼠标单击来更改当前项目。
-
当当前项目改变时,会发射 currentItemChanged(current:QListWidgetItem,previous:QListWidgetItem)信号current和previous 分别表示当前项目和以前的项目。
-
其他信号与槽举例如下
-
currentRowChanged(currentRowint):当当前项目改变时触发该信号,currentRow是当前行的行号,如果没有当前项目则返回-1。
-
currentTextChanged(currentText;str):当当前项目改变时触发该信号,currentText是当前行的 text,如果没有当前项目则返回None。
-
itemActivated(item:QListWidgetItem):当项目被激活时触发该信号。根据系统配置当用户单击或双击该项目时会激活该项目。当用户按下激活键时该项目也会被激活(在Windows和X11上这是返回键,在macOSX上是Command+O)。
-
itemChanged(item:QListWidgetItem): 当项目的data 发生变化时触发该信号。
-
itemClicked(item:QListWidgetItem):当鼠标单击项目时触发该信号。
-
itemDoubleClicked(item:QListWidgetItem):当鼠标双击项目时触发该信号
-
itemEntered(item:QListWidgetItem):当鼠标指针进入一个项目时会发该信号。该信号仅在打开mouseTracking(使用 setMouseTracking设置)或移到项目中按下鼠标按键时发射。
-
itemPressed(item:QListWidgetItem):当在项目上按下鼠标按键时触发该信号。当选择发生变化时触发该信号itemSelectionChanged0):
-
上下文菜单
前面已经介绍了两种添加上下文菜单的用法,即重写 contextMenuEvent()函数或createPopupMenu()函数。
这两个函数对于一般的窗口可用,但是对于一些特殊的控件不可用,如 QLineEdit、QTextEdit 等,这些控件有其特殊的上下文菜单环境。可以使用setContextMenuPolicy()函数和 customContextMenuRequested 信号来改写默认设置,具体的用法可参考以下实例。
列表控件QListWidget的应用实例
这里用setMouseTracking0函数打开了鼠标跟踪(默认关闭),否则只有单击鼠标按键后才能追踪到鼠标位置,但是无法获取鼠标的实时移动信息。需要注意的是,默认 StatusTip 和 WhatsThis 都是关闭的,因此需要把它们打开。打开StatusTp 的方式很简单
# 开启 statusbar
statusBar = self.statusBar()
statusBar.show()
打开 WhatsThis 则有些复杂,这里提供两种打开方式一种是 QAction,另一种是QToolButton,两者都在工具栏中显示,并且效果是一样的。
前者通过 QWhatsThiscreateAction0函数返回一个 QAction,当这个QAction 被触发时会自动进入"What’s This??模式,并且这种方式可以直接集成到上下文菜单中;
后者先新建 QtoolButton 按钮,再单击主动触发OWhatsThisnterWhatsThisMode0函数进入"What’sThis?"模式。代码如下
# 开启whatsThis功能
whatsThis = QWhatsThis(self)
toolbar = self.addToolBar('help')
# 方式1:QAction
self.actionHelp = whatsThis.createAction(self)
self.actionHelp.setText('显示whatsThis-help')
# self.actionHelp.setShortcuts(QKeySequence(Qt.CTRL | Qt.Key_H))
self.actionHelp.setShortcuts(QKeySequence(Qt.CTRL | Qt.Key_H))
toolbar.addAction(self.actionHelp)
# 方式2:工具按钮
tool_button = QToolButton(self)
tool_button.setToolTip("显示whatsThis2-help")
tool_button.setIcon(QIcon("images/help.jpg"))
toolbar.addWidget(tool_button)
tool_button.clicked.connect(lambda: whatsThis.enterWhatsThisMode())
用户既可以通过单击或按 Esc键退出"What’s This?"模式,也可以通过QWhatsThis.leaveWhatsThisMode0函数用程序退出"What’s This?"模式。
这里只对"set 提示-ToolTip,StatusTip,WhatsThis"和"setFont、Fore(Back)ground"在
"What’s This?"模式下提供了帮助信息。
需要注意的是,关于WhatsThis 提示,PySide 6使用的是类实例方法 whatsThiscreateAction(self),而 PyQt 6 只能使用静态方法,也就是QWhatsThiscreateAction(self);对于 whatsThisenterWhatsThisMode()也一样。
下面列举了一些常用的信号与槽的使用方法,每个信号的触发都会在QPlainTextEdit 中显示相应的信息。使用方法如下(槽函数onItemActivated()、onItemClicked()等都比较简单,这里不再赘述);
# 信号与槽
self.listWidget.currentItemChanged[QListWidgetItem,QListWidgetItem].connect(self.onCurrentItemChanged)
self.listWidget.currentRowChanged[int].connect(lambda x: self.text.appendPlainText(f'"row:{x}"触发currentRowChanged信号:'))
self.listWidget.currentTextChanged[str].connect(lambda x: self.text.appendPlainText(f'"text:{x}"触发currentTextChanged信号:'))
self.listWidget.itemActivated[QListWidgetItem].connect(self.onItemActivated)
self.listWidget.itemClicked[QListWidgetItem].connect(self.onItemClicked)
self.listWidget.itemDoubleClicked[QListWidgetItem].connect(lambda item: self.text.appendPlainText(f'"{item.text()}"触发itemDoubleClicked信号:'))
self.listWidget.itemChanged[QListWidgetItem].connect(lambda item: self.text.appendPlainText(f'"{item.text()}"触发itemChanged信号:'))
self.listWidget.itemEntered[QListWidgetItem].connect(lambda item: self.text.appendPlainText(f'"{item.text()}"触发itemEntered信号:'))
self.listWidget.itemPressed[QListWidgetItem].connect(lambda item: self.text.appendPlainText(f'"{item.text()}"触发itemPressed信号:'))
self.listWidget.itemSelectionChanged.connect(lambda: self.text.appendPlainText(f'触发itemSelectionChanged信号:'))
上下文菜单的使用方法如下(这里使用快捷方式设置选项的文本、槽函数和快捷键,但是对"删除"选项额外添加了图片,对"全不选"选项没有配置快捷键):
# 上下文菜单
self.menu = self.generateMenu()
self.listWidget.setContextMenuPolicy(Qt.CustomContextMenu)# 允许右键产生子菜单
self.listWidget.customContextMenuRequested.connect(self.showMenu)# 右键菜单
def generateMenu(self):
menu = QMenu(self)
menu.addAction('增加',self.onAdd,QKeySequence(Qt.CTRL | Qt.Key_N))
menu.addAction('插入',self.onInsert,QKeySequence(Qt.CTRL | Qt.Key_I))
menu.addAction(QIcon("images/close.png"),'删除',self.onDelete,QKeySequence(Qt.CTRL | Qt.Key_D))
menu.addSeparator()
menu.addAction('全选',self.onCheckAll,QKeySequence(Qt.CTRL | Qt.Key_A))
menu.addAction('反选',self.onCheckInverse,QKeySequence(Qt.CTRL | Qt.Key_R))
menu.addAction('全不选',self.onCheckInverse)
menu.addSeparator()
menu.addAction(self.actionHelp)
return menu
def showMenu(self,pos):
self.menu.exec(QCursor.pos())# 显示菜单
# -*- coding: UTF-8 -*-
# File date: Hi_2023/3/26 19:33
# File_name: 02-QListWidget及上下文菜单.py
from PySide6.QtWidgets import *
from PySide6.QtGui import *
from PySide6.QtCore import *
import sys
import os
os.chdir(os.path.dirname(__file__))
class QListWidgetDemo(QMainWindow):
addCount = 0
insertCount = 0
def __init__(self,parent=None):
super(QListWidgetDemo,self).__init__(parent)
self.setWindowTitle("QListWidget案例")
self.text = QPlainTextEdit('用来显示QListWidget相关信息:')
self.listWidget = QListWidget()
# 增删
self.buttonDelete = QPushButton('删除')
self.buttonAdd = QPushButton('增加')
self.buttonInsert = QPushButton('插入')
layoutH = QHBoxLayout()
layoutH.addWidget(self.buttonAdd)
layoutH.addWidget(self.buttonInsert)
layoutH.addWidget(self.buttonDelete)
self.buttonAdd.clicked.connect(self.onAdd)
self.buttonInsert.clicked.connect(self.onInsert)
self.buttonDelete.clicked.connect(self.onDelete)
# 选择
self.buttonCheckAll = QPushButton('全选')
self.buttonCheckInverse = QPushButton('反选')
self.buttonCheckNone = QPushButton('全不选')
layoutH2 = QHBoxLayout()
layoutH2.addWidget(self.buttonCheckAll)
layoutH2.addWidget(self.buttonCheckInverse)
layoutH2.addWidget(self.buttonCheckNone)
self.buttonCheckAll.clicked.connect(self.onCheckAll)
self.buttonCheckInverse.clicked.connect(self.onCheckInverse)
self.buttonCheckNone.clicked.connect(self.onCheckNone)
layout = QVBoxLayout(self)
layout.addWidget(self.listWidget)
layout.addLayout(layoutH)
layout.addLayout(layoutH2)
layout.addWidget(self.text)
widget = QWidget()
self.setCentralWidget(widget)
widget.setLayout(layout)
# 添加item
for n in range(3):
_str = 'item row {0}'.format(n)
self.listWidget.addItem(_str)
self.listWidget.addItem(QListWidgetItem('haha'))
QListWidgetItem('haha2',self.listWidget)
self.listWidget.insertItem(2,'item insert')
# flag 和 check
for i in range(self.listWidget.count()):
item = self.listWidget.item(i)
item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled)
# item.setFlags(Qt.NoItemFlags)
item.setCheckState(Qt.Unchecked)
# setText
item.setText('setText-右对齐')
item.setTextAlignment(Qt.AlignRight)
item.setCheckState(Qt.Checked)
# selection
# self.listWidget.setSelectionMode(QAbstractItemView.SingleSelection)
self.listWidget.setSelectionMode(QAbstractItemView.ExtendedSelection)
self.listWidget.setSelectionBehavior(QAbstractItemView.SelectRows)
# setIcon
item = QListWidgetItem('setIcon')
item.setIcon(QIcon('images/music.png'))
self.listWidget.addItem(item)
# setFont、setFore(Back)ground
item = QListWidgetItem('setFont、Fore(Back)ground')
item.setFont(QFont('宋体'))
item.setForeground(QBrush(QColor(255,0,0)))
item.setBackground(QBrush(QColor(0,255,0)))
item.setWhatsThis('whatsThis提示1-setFont、Fore(Back)ground')
self.listWidget.addItem(item)
# setToolTip,StatusTip,WhatsThis
item = QListWidgetItem('set提示-ToolTip,StatusTip,WhatsThis')
item.setToolTip('toolTip提示')
item.setStatusTip('statusTip提示')
item.setWhatsThis('whatsThis提示2')
self.listWidget.setMouseTracking(True)
self.listWidget.addItem(item)
# 开启statusbar
statusBar = self.statusBar()
statusBar.show()
# 开启whatsThis功能
whatsThis = QWhatsThis(self)
toolbar = self.addToolBar('help')
# 方式1:QAction
self.actionHelp = whatsThis.createAction(self)
self.actionHelp.setText('显示whatsThis-help')
# self.actionHelp.setShortcuts(QKeySequence(Qt.CTRL | Qt.Key_H))
self.actionHelp.setShortcuts(QKeySequence(Qt.CTRL | Qt.Key_H))
toolbar.addAction(self.actionHelp)
# 方式2:工具按钮
tool_button = QToolButton(self)
tool_button.setToolTip("显示whatsThis2-help")
tool_button.setIcon(QIcon("images/help.jpg"))
toolbar.addWidget(tool_button)
tool_button.clicked.connect(lambda: whatsThis.enterWhatsThisMode())
# 上下文菜单
self.menu = self.generateMenu()
self.listWidget.setContextMenuPolicy(Qt.CustomContextMenu)######允许右键产生子菜单
self.listWidget.customContextMenuRequested.connect(self.showMenu)####右键菜单
# 信号与槽
self.listWidget.currentItemChanged[QListWidgetItem,QListWidgetItem].connect(self.onCurrentItemChanged)
self.listWidget.currentRowChanged[int].connect(
lambda x: self.text.appendPlainText(f'"row:{x}"触发currentRowChanged信号:'))
self.listWidget.currentTextChanged[str].connect(
lambda x: self.text.appendPlainText(f'"text:{x}"触发currentTextChanged信号:'))
self.listWidget.itemActivated[QListWidgetItem].connect(self.onItemActivated)
self.listWidget.itemClicked[QListWidgetItem].connect(self.onItemClicked)
self.listWidget.itemDoubleClicked[QListWidgetItem].connect(
lambda item: self.text.appendPlainText(f'"{item.text()}"触发itemDoubleClicked信号:'))
self.listWidget.itemChanged[QListWidgetItem].connect(
lambda item: self.text.appendPlainText(f'"{item.text()}"触发itemChanged信号:'))
self.listWidget.itemEntered[QListWidgetItem].connect(
lambda item: self.text.appendPlainText(f'"{item.text()}"触发itemEntered信号:'))
self.listWidget.itemPressed[QListWidgetItem].connect(
lambda item: self.text.appendPlainText(f'"{item.text()}"触发itemPressed信号:'))
self.listWidget.itemSelectionChanged.connect(lambda: self.text.appendPlainText(f'触发itemSelectionChanged信号:'))
def generateMenu(self):
menu = QMenu(self)
menu.addAction('增加',self.onAdd,QKeySequence(Qt.CTRL | Qt.Key_N))
menu.addAction('插入',self.onInsert,QKeySequence(Qt.CTRL | Qt.Key_I))
menu.addAction(QIcon("images/close.png"),'删除',self.onDelete,QKeySequence(Qt.CTRL | Qt.Key_D))
menu.addSeparator()
menu.addAction('全选',self.onCheckAll,QKeySequence(Qt.CTRL | Qt.Key_A))
menu.addAction('反选',self.onCheckInverse,QKeySequence(Qt.CTRL | Qt.Key_R))
menu.addAction('全不选',self.onCheckInverse)
menu.addSeparator()
menu.addAction(self.actionHelp)
return menu
def showMenu(self,pos):
self.menu.exec(QCursor.pos())# 显示菜单
def contextMenuEvent(self,event):
menu = QMenu(self)
menu.addAction('选项1')
menu.addAction('选项2')
menu.addAction('选项3')
menu.exec(event.globalPos())
def onCurrentItemChanged(self,current: QListWidgetItem,previous: QListWidgetItem):
if previous == None:
_str = f'触发currentItemChanged信号,当前项:"{current.text()}",之前项:None'
else:
_str = f'触发currentItemChanged信号,当前项:"{current.text()}",之前项:"{previous.text()}"'
self.text.appendPlainText(_str)
def onItemClicked(self,item: QListWidgetItem):
self.listWidget.currentRow()
row = self.listWidget.row(item)
if row == 0:
_str1 = f'当前点击:"{item.text()}",上一个:None,下一个:"{self.listWidget.item(row + 1).text()}"'
elif row == self.listWidget.count()- 1:
_str1 = f'当前点击:"{item.text()}",上一个:"{self.listWidget.item(row - 1).text()}",下一个:None'
else:
_str1 = f'当前点击:"{item.text()}",上一个:"{self.listWidget.item(row - 1).text()}",下一个:"{self.listWidget.item(row + 1).text()}"'
if item.checkState()== Qt.Unchecked:
item.setCheckState(Qt.Checked)
_str2 = f'"{item.text()}"被选中'
else:
item.setCheckState(Qt.Unchecked)
_str2 = f'"{item.text()}"被取消选中'
self.text.appendPlainText(f'"{item.text()}"触发itemClicked信号:')
self.text.appendPlainText(_str1)
self.text.appendPlainText(_str2)
return
def onItemActivated(self,item: QListWidgetItem):
self.text.appendPlainText(f'"{item.text()}"触发itemActivated信号:')
return
def onAdd(self):
self.addCount += 1
text = f'新增-{self.addCount}'
self.listWidget.addItem(text)
self.text.appendPlainText(f'新增item:"{text}"')
def onInsert(self):
self.insertCount += 1
row = self.listWidget.currentRow()
text = f'插入-{self.insertCount}'
self.listWidget.insertItem(row,text)
self.text.appendPlainText(f'row:{row},新增item:"{text}"')
def onDelete(self):
row = self.listWidget.currentRow()
item = self.listWidget.item(row)
self.listWidget.takeItem(row)
self.text.appendPlainText(f'row:{row},删除item:"{item.text()}"')
def onCheckAll(self):
self.text.appendPlainText('点击了"全选"')
count = self.listWidget.count()
for i in range(count):
item = self.listWidget.item(i)
item.setCheckState(Qt.Checked)
def onCheckInverse(self):
self.text.appendPlainText('点击了"反选"')
count = self.listWidget.count()
for i in range(count):
item = self.listWidget.item(i)
if item.checkState()== Qt.Unchecked:
item.setCheckState(Qt.Checked)
else:
item.setCheckState(Qt.Unchecked)
def onCheckNone(self):
self.text.appendPlainText('点击了"全不选"')
count = self.listWidget.count()
for i in range(count):
item = self.listWidget.item(i)
item.setCheckState(Qt.Unchecked)
if __name__ =="__main__":
app = QApplication(sys.argv)
demo = QListWidgetDemo()
demo.show()
sys.exit(app.exec())
下面的程序建立一个自定义对话框,通过菜单显示对话框。
对话框中放置两个列表控件第1个列表控件中放置可选科目,对每个项根据其所在的行把行号定义成项的角色值单击其中的项,将会移到第2个列表控件中,且按照角色值顺序插入,
同样,单击第2个列表控件中的项,也是按照角色值顺序插入到第1个列表控件中,单击对话框中的"确定"按钮,会把第2个列表控件中的内容输出到主界面上。
# -*- coding: UTF-8 -*-
# File date: Hi_2023/3/4 15:43
# File_name: 01-列表控件QListWidget的应用实例.py
import sys
from PySide6.QtWidgets import(QApplication,QDialog,QWidget,QPushButton,QMenuBar,QLabel,QGridLayout,QListWidget,QTextBrowser,QVBoxLayout,QHBoxLayout,QFileDialog)
from PySide6.QtCore import Qt
class MyDialog(QDialog):
def __init__(self,parent=None):
super().__init__(parent)
self.setupui()
def setupui(self):
label1 = QLabel("选修课科目")
label2 = QLabel("已选科目")
self.listWidget_available = QListWidget()# 列表控件
self.listWidget_selected = QListWidget()# 列表控件
btn_ok = QPushButton("确定")
btn_cancel = QPushButton("取消")
h = QHBoxLayout()
h.addStretch(1)
h.addWidget(btn_ok)
h.addWidget(btn_cancel)
grid = QGridLayout(self)# 标签、列表框采用格棚布局
grid.addWidget(label1,0,0)
grid.addWidget(label2,0,1)
grid.addWidget(self.listWidget_available,1,0)
grid.addWidget(self.listWidget_selected,1,1)
grid.addLayout(h,2,0,1,2)
class_available =["语文0","数学1","物理2","化学3","地理4","历史5","生物6","哲学7","测量8"]
self.listWidget_available.addItems(class_available)# 添加项
for i in range(self.listWidget_available.count()): # 用角色数据记录项的初始位置
item = self.listWidget_available.item(i)# 获取项
item.setData(Qt.UserRole,i)# 设置项的角色值,值为行号
self.listWidget_available.itemClicked.connect(self.listWidget_available_clicked)
self.listWidget_selected.itemClicked.connect(self.listWidget_selected_clicked)
btn_ok.clicked.connect(self.btn_ok_clicked)
btn_cancel.clicked.connect(self.btn_cancel_clicked)
#"确定"按钮的单击#"取消"按钮的单击
def listWidget_available_clicked(self,item): # 列表控件的单击槽函数
row = self.listWidget_available.row(item)# 获取项的行号
self.listWidget_available.takeItem(row)# 移除项
i = item.data(Qt.UserRole)# 移除项的角色值
for j in range(self.listWidget_selected.count()):
if i < self.listWidget_selected.item(j).data(Qt.UserRole):
self.listWidget_selected.insertItem(j,item)# 根据角色值插人到列表中
self.listWidget_selected.addItem(item)
def listWidget_selected_clicked(self,item): # 列表控件的单击槽函数
row = self.listWidget_selected.row(item)
self.listWidget_selected.takeItem(row)
i = item.data(Qt.UserRole)
for j in range(self.listWidget_selected.count()):
if i < self.listWidget_available.item(j).data(Qt.UserRole):
self.listWidget_available.insertItem(j,item)# 根据角色值插人到列表中
self.listWidget_available.addItem(item)
def btn_ok_clicked(self): #"确定"按钮的槽函数
self.setResult(QDialog.Accepted)
self.setVisible(False)
def btn_cancel_clicked(self): #"取消"按钮的槽函数
self.setResult(QDialog.Rejected)
self.setVisible(False)
class MyWindow(QWidget):
def __init__(self,parent=None):
super().__init__(parent)
self.widget_setupUi()
def widget_setupUi(self): # 建立主程序界面
menuBar = QMenuBar(self)# 定义菜单栏
file_menu = menuBar.addMenu("文件(E)")# 定义菜单
# 添加动作
action_selection = file_menu.addAction("选修课(&C)")
action_save = file_menu.addAction("保存(&S")
file_menu.addSeparator()
action_exit = file_menu.addAction("退出(&E)")
self.textBrowser = QTextBrowser(self)# 显示数据控件#主程序界面的布局
v = QVBoxLayout(self)
v.addWidget(menuBar)
v.addWidget(self.textBrowser)
action_selection.triggered.connect(self.action_selection_triggered)
action_save.triggered.connect(self.action_save_triggered)# 信号与槽的连接
action_exit.triggered.connect(self.close)# 退出动作的信号与窗口关闭的连接
def action_selection_triggered(self): # 自定义槽函数
dialog = MyDialog(self)# 自定义对话框实例
if dialog.exec(): # 模式显示对话框
n = dialog.listWidget_selected.count()
text ="你选择的选修课是:"
if n > 0:
for i in range(n):
text = text +""+ dialog.listWidget_selected.item(i).text()
self.textBrowser.append(text)
else:
self.textBrowser.append("你没有选择任何选修课!")
def action_save_triggered(self): # 自定义槽函数
string = self.textBrowser.toPlainText()
if len(string)> 0:
filename,filter = QFileDialog.getSaveFileName(self,"保存文件",".","文本文件(*.txt)")
if len(filename)> 0:
fp = open(filename,"a+",encoding="UTE -8")
fp.writelines(string)
fp.close()
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MyWindow()
win.show()
sys.exit(app.exec())