1. 官方文档
https://www.riverbankcomputing.com/static/Docs/PyQt6/api/qtwidgets/qcombobox.html
2. 概述
枚举值 | 使用示例 | 描述 |
InsertPolicy | 参考代码部分 <about_InsetPolicy> | 可编辑模式下使用; 设置用户在可编辑的文本框中,输入一个新的字符串后,新字符插入的策略; 如InsertAtBottom、InsertBeforeCurrent、InsertAlphabetically等。 |
SizeAdjustPolicy | 参考代码部分 <about_SizeAdjustPolicy> | 指定窗口部件的大小调整策略; AdjustToContents: 自动调整大小以适应内容; AdjustToContentsOnFirstShow: 第一次显示时自动调整大小以适应内容; AdjustToMinimumContentsLength WithIcon:将控件宽度调整为minimumContentLength()值加一个图标的大小。出于性能原因,请在大型模型上使用此策略。 |
方法 | 使用示例 | 描述 |
addItem(Optional[str], userData: Any = None) | <about_add_insert> | 添加一个选项 |
addItem(QIcon, Optional[str], userData: Any = None) | <about_add_insert> | 添加一个带图标的选项 |
addItems(Iterable[Optional[str]]) | <about_add_insert> | 添加一个或多个选项 |
insertItem(int, Optional[str], userData: Any = None) | <about_add_insert> | 插入一个选项 |
insertItem(int, QIcon, Optional[str], userData: Any = None) | <about_add_insert> | 插入一个带图标的选项 |
insertItems(int, Iterable[Optional[str]]) | <about_add_insert> | 插入一个或多个选项 |
insertSeparator(int) | <about_add_insert> | 如果插入了分隔线,分割线会占用一个index |
setItemText(int, Optional[str])) | <about_item_current_1> | 设置指定索引对应选项的内容 |
setItemData(int, Any, role: int = UserRole) | <about_add_insert> <about_item_current_1> | 设置指定索引对应选项的数据 |
setItemIcon(int, QIcon) | <about_item_current_1> <about_item_current_2> | 设置指定索引对应选项的图片 |
itemText(int) → str | <about_item_current_2> | 获取指定索引对应选项的内容 |
itemData(int, role: int = UserRole) → Any | <about_add_insert> <about_item_current_2> | 获取指定索引对应选项的数据 |
itemIcon(int) → QIcon | <about_item_current_2> | 获取指定索引对应选项的图片 |
clear() | <about_editable> | 删除所有选项 |
clearEditText() | <about_editable> | 可编辑模式或通过setLineEdit 添加了文本框时,可使用此命令清空文本框内容;不存在文本框时无操作 |
currentIndex() → int | <about_item_current_1> | 获取当前选择的选项索引 |
currentText() → str | <about_item_current_1> | 获取当前选择的选项内容 |
currentData(role: int = UserRole) → Any | <about_item_current_1> | 获取当前选择的选项数据 |
setCurrentIndex(int) | <about_item_current_2> | 设置当前选项的索引 |
setCurrentText(Optional[str]) | <about_item_current_2> | 设置当前选项的内容 |
setIconSize(QSize) | <about_add_insert> | 设置选项中图尺寸 |
iconSize() → QSize | <about_add_insert> | 获取图尺寸 |
count() → int | <about_count> | 返回下拉选项总数 |
setMaxCount(int) | <about_count> | 超过的选项将不被显示 |
maxCount() → int | <about_count> | 最多选项数 |
setMaxVisibleItems(int) | <about_count> | 超过的选项将在下一页显示,需要拖动滑块 |
maxVisibleItems() → int | <about_count> | 一页最大项目数 |
setEditable(bool) | <about_editable> | 设置可编辑模式 |
isEditable() → bool | <about_editable> | 是否可编辑 |
setDuplicatesEnabled(bool) | <about_editable> | 设置是否允许重复添加,默认为False;仅针对可编辑模式下,用户通过文本框输入的内容,下拉框中已存在时,是否重复添加。 |
duplicatesEnabled() → bool | <about_editable> | 否允许重复添加 |
setFrame(bool) | <about_editable> | 设置文本框是否有外框 针对可编辑模式 |
hasFrame() → bool | <about_editable> | 文本框是否有外框 |
setLineEdit(QLineEdit) | <about_editable> | 设置文本框 |
lineEdit() → QLineEdit | <about_editable> | 非可编辑模式下默认为None;在可编辑模式下,或已经通过setLineEdit添加过文本框时,为QLineEdit对象 |
setEditText(Optional[str]) | <about_editable> | 设置文本框中的内容 |
setInsertPolicy(insertPolicy) | <about_InsetPolicy> | 参考InsertPolicy |
insertPolicy() → insertPolicy | <about_InsetPolicy> | 参考InsertPolicy |
setSizeAdjustPolicy( SizeAdjustPolic) | <about_SizeAdjustPolicy> | 参考SizeAdjustPolicy |
sizeAdjustPolicy() → sizeAdjustPolicy | <about_SizeAdjustPolicy> | 参考SizeAdjustPolicy |
3. 完整代码
from PyQt6.QtCore import QSize
from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton, QComboBox, QLineEdit, QCompleter, QLabel
import sys
class Ui_Study(QMainWindow):
def __init__(self):
super().__init__()
self.resize(500, 500)
self.setMinimumSize(500, 500)
# 增加3个下拉选项框、3个按钮、3个label、3个文本框,便于验证各个功能点
self.combobox0 = QComboBox(self)
self.combobox1 = QComboBox(self)
self.combobox2 = QComboBox(self)
self.pushbutton0 = QPushButton(self)
self.pushbutton1 = QPushButton(self)
self.pushbutton2 = QPushButton(self)
self.label0 = QLabel(self)
self.label1 = QLabel(self)
self.label2 = QLabel(self)
self.lineedit0 = QLineEdit(self)
self.lineedit1 = QLineEdit(self)
self.lineedit2 = QLineEdit(self)
self.initial_add()
self.name_list = ['Oliver', 'Emma', 'Noah', 'Ava', 'William',
'Sophia', 'James', 'Isabella', 'Benjamin', 'Mia',
'Lucas', 'Charlotte', 'Henry', 'Amelia', 'Alexander',
'Harper', 'Michael', 'Evelyn', 'Ethan', 'Abigail']
self.name_count = 0
func_name = 'about_editable'
# 'about_InsetPolicy', 'about_SizeAdjustPolicy', 'about_editable', 'about_add_insert',
# 'about_item_current_1', 'about_item_current_2', 'about_count'
getattr(self, func_name)()
self.show()
def initial_add(self):
self.combobox0.move(20, 20)
self.combobox1.move(20, 60)
self.combobox2.move(20, 100)
self.pushbutton0.move(20, 140)
self.pushbutton0.resize(200, 30)
self.pushbutton1.move(20, 180)
self.pushbutton1.resize(200, 30)
self.pushbutton2.move(20, 220)
self.pushbutton2.resize(200, 30)
self.label0.move(20, 260)
self.label0.resize(200, 30)
self.label1.move(20, 300)
self.label1.resize(200, 30)
self.label2.move(20, 340)
self.label2.resize(200, 30)
self.lineedit0.move(230, 260)
self.lineedit0.resize(200, 30)
self.lineedit1.move(230, 300)
self.lineedit1.resize(200, 30)
self.lineedit2.move(230, 340)
self.lineedit2.resize(200, 30)
def about_InsetPolicy(self):
self.combobox0.resize(200, 30)
self.combobox1.resize(200, 30)
self.combobox0.setInsertPolicy(QComboBox.InsertPolicy.InsertAtCurrent)
self.combobox1.addItems(["InsertAfterCurrent", "InsertAlphabetically", "InsertAtBottom", "InsertAtCurrent",
"InsertAtTop", "InsertBeforeCurrent", "NoInsert"])
self.combobox1.currentTextChanged.connect(
lambda text: self.combobox0.setInsertPolicy(getattr(QComboBox.InsertPolicy, text)))
self.combobox0.setEditable(True)
self.combobox0.addItems(["A", "B", "C", "D"])
self.pushbutton0.setText("AddItem(固定添加在列表最后)")
def addName():
self.combobox1.setInsertPolicy(getattr(QComboBox.InsertPolicy, self.combobox1.currentText()))
self.combobox0.addItem(f'{self.name_list[self.name_count]}')
self.name_count += 1
self.pushbutton0.clicked.connect(addName)
def about_SizeAdjustPolicy(self):
self.combobox0.addItems(self.name_list + ['Lucas Candy MILLER Mary'])
self.combobox0.setEditable(True) # 可以注释掉对比看看
print(self.combobox0.minimumContentsLength())
print(self.combobox0.sizeAdjustPolicy())
print(self.combobox1.width())
print('\n')
# 如果用resize设置了控件尺寸,SizeAdjustPolicy不起作用,可以设置self.combobox0.resize(200, 30)对比看一看
# self.combobox1.addItems(self.name_list + ['Lucas Candy MILLER Mary'])
self.combobox1.setMinimumContentsLength(30) # 可以设置为0、20、30对比看一看
self.combobox1.setEditable(True) # 可以注释掉对比看看
self.combobox1.lineEdit().setReadOnly(True) # 可以注释掉对比看看
self.combobox1.setSizeAdjustPolicy(QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon)
print(self.combobox1.minimumContentsLength())
print(self.combobox1.sizeAdjustPolicy())
print(self.combobox1.width())
self.combobox2.setSizeAdjustPolicy(QComboBox.SizeAdjustPolicy.AdjustToContents)
self.combobox2.addItems(self.name_list + ['Lucas Candy MILLER Mary'])
print(self.combobox2.minimumContentsLength())
print(self.combobox2.sizeAdjustPolicy())
def addName():
self.combobox0.addItem('Charles André Joseph Pierre Marie de Gaulle')
self.combobox1.addItem('Charles André Joseph Pierre Marie de Gaulle')
self.combobox2.addItem('Charles André Joseph Pierre Marie de Gaulle')
self.pushbutton0.setText("添加一个长内容")
self.pushbutton0.clicked.connect(addName)
def about_editable(self):
self.combobox0.resize(200, 30)
self.combobox1.resize(200, 30)
self.combobox2.resize(200, 30)
# combobox0
self.combobox0.setEditable(True)
self.combobox0.addItems(self.name_list[:5])
self.label0.setText('combobox0是否可编辑: ')
self.lineedit0.setText(str(self.combobox0.isEditable()))
print(f'可编辑模式下的lineEdit: {self.combobox0.lineEdit()}')
# combobox1
# 关于lineEdit()
self.combobox1.addItems(self.name_list[:5])
self.label1.setText('combobox1是否可编辑: ')
self.lineedit1.setText(str(self.combobox1.isEditable()))
print(f'不可编辑模式下的lineEdit: {self.combobox1.lineEdit()}') # 非可编辑模式下,不存在linedit,返回None
self.combobox1.setLineEdit(QLineEdit(self.combobox1)) # 可以通过setLineEdit添加一个linedit
print(f'不可编辑模式+通过setlineEdit设置后: {self.combobox1.lineEdit()}')
self.combobox1.currentIndexChanged.connect(
lambda: self.combobox1.lineEdit().setText(str(self.combobox1.currentIndex()))
) # 可以设置lineEdit()的内容
self.combobox1.lineEdit().setReadOnly(True) # 加一个readonly,用户不能编辑其内容
# combobox2
# duplicate\frame
self.combobox2.addItems((self.name_list[:5]))
self.combobox2.clearEditText()
self.combobox2.setEditable(True)
print(f'默认值-是否有框架:{self.combobox2.hasFrame()}')
print(f'默认值-是否可重复:{self.combobox2.duplicatesEnabled()}')
self.combobox2.setFrame(False)
# 在文本框内输入内容,看一看无frame、不可重复的效果
self.combobox2.addItems(self.name_list[:5]) # 对addItem无效
self.combobox2.setEditText('This is a sentence')
# pushbutton0-clear()
self.pushbutton0.setText('combobox1执行clear()')
def combobox1_clear():
self.combobox1.clear()
self.pushbutton0.clicked.connect(combobox1_clear)
self.pushbutton1.setText('combobox1添加内容')
# pushbutton0-addItems()
def combobox1_add():
self.combobox1.addItems(self.name_list[:5])
self.pushbutton1.clicked.connect(combobox1_add)
# pushbutton2-clearEditText()
self.pushbutton2.setText('combobox0和1执行clearEditText()')
def combobox0_clearEditText():
self.combobox0.clearEditText()
self.combobox1.clearEditText()
self.pushbutton2.clicked.connect(combobox0_clearEditText)
def about_add_insert(self):
self.combobox0.resize(200, 30)
self.combobox1.resize(200, 30)
# Combobox1
print(self.combobox1.iconSize())
self.combobox1.setIconSize(QSize(40, 40))
self.combobox1.addItem(QIcon('Flower.PNG'), 'add-0')
# Combobox0
self.combobox0.addItem('add-1', 'dataA of add-1') # addItem
self.combobox0.setItemData(0, 'dataB of add-1', 3) # setItemData
self.combobox0.setItemData(0, QIcon('C.PNG'), 1)
self.label0.setText('data-role')
self.lineedit0.setText(self.combobox0.itemData(0)) # UserRole # itemData
self.label1.setText('data-role=3 ')
self.lineedit1.setText(self.combobox0.itemData(0, 3))
self.label2.setText('data-role=2')
self.lineedit2.setText(self.combobox0.itemData(0, 2))
self.combobox0.setItemData(0, 'add-1-new', 2)
self.combobox0.addItem(QIcon('C.PNG'), 'add-2') # addItem
self.combobox0.addItems(self.name_list[:3]) # addItems
self.pushbutton0.setText("No1: 0-插入带图at0;2-插入at2")
self.pushbutton1.setText("No1: 2-插入分割线;4-插入at4")
def combobox0_insert0():
self.combobox0.insertItem(0, QIcon('C.PNG'), 'at0') # insertItem
self.combobox0.insertItem(2, 'at2') # insetItem
def combobox0_insert1():
self.combobox0.insertSeparator(2)
self.combobox0.insertItems(4, ['at4-1', 'at4-2', 'at4-3']) # insertItems
self.pushbutton0.clicked.connect(combobox0_insert0)
self.pushbutton1.clicked.connect(combobox0_insert1)
pass
def about_item_current_1(self):
self.combobox0.resize(200, 30)
self.combobox0.addItems(self.name_list[:5])
self.pushbutton0.setText('修改选项1的内容、数据、图片')
def setItem1():
self.combobox0.setItemText(1, 'A')
self.combobox0.setItemData(1, 'LALALALA')
self.combobox0.setItemIcon(1, QIcon('Flower.PNG'))
self.pushbutton0.clicked.connect(setItem1)
self.label0.setText('当前选项Index')
self.label1.setText('当前选项内容')
self.label2.setText('当前选项数据')
self.combobox0.currentIndexChanged.connect(
lambda: self.lineedit0.setText(str(self.combobox0.currentIndex()))
)
self.combobox0.currentIndexChanged.connect(
lambda: self.lineedit1.setText(str(self.combobox0.currentText()))
)
self.combobox0.currentIndexChanged.connect(
lambda: self.lineedit2.setText(str(self.combobox0.currentData()))
)
pass
def about_item_current_2(self):
self.combobox0.resize(200, 30)
self.combobox0.addItems(self.name_list[:5])
self.combobox0.insertItem(1, QIcon('Flower.PNG'), 'A', 'LALALALA')
self.pushbutton0.setText('给选项3添加选项1的图片')
self.pushbutton0.clicked.connect(lambda: self.combobox0.setItemIcon(3, self.combobox0.itemIcon(1)))
self.pushbutton1.setText('将当前选项设置为选项1(基于索引)')
self.pushbutton1.clicked.connect(lambda: self.combobox0.setCurrentIndex(1))
self.pushbutton2.setText('将当前选项设置为A(选项1的内容)')
self.pushbutton2.clicked.connect(lambda: self.combobox0.setCurrentText('A'))
self.label0.setText('第1个选项的内容')
self.label1.setText('第1个选项的数据')
self.combobox0.currentIndexChanged.connect(
lambda: self.lineedit0.setText(str(self.combobox0.itemText(1)))
)
self.combobox0.currentIndexChanged.connect(
lambda: self.lineedit1.setText(str(self.combobox0.itemData(1)))
)
def about_count(self):
self.combobox0.addItems(self.name_list)
self.pushbutton0.setText('最大项目数设置为10')
self.pushbutton0.clicked.connect(lambda: self.combobox0.setMaxCount(10))
self.pushbutton1.setText('一页最大项目数设置为5')
self.pushbutton1.clicked.connect(lambda: self.combobox0.setMaxVisibleItems(5))
self.pushbutton2.setText('更新配置')
self.label0.setText('当前项目总数')
self.label1.setText('最大项目数')
self.label2.setText('一页最大项目数')
def update_count():
self.lineedit0.setText(str(self.combobox0.count()))
self.lineedit1.setText(str(self.combobox0.maxCount()))
self.lineedit2.setText(str(self.combobox0.maxVisibleItems()))
self.pushbutton2.clicked.connect(update_count)
if __name__ == '__main__':
app = QApplication(sys.argv)
my_ui = Ui_Study()
sys.exit(app.exec())
4. 细节说明
1. InsertPolicy、insertPolicy()、setInsetPolicy()
(1)上述枚举值和方法均仅针对editable combobox,即在文本框输入一定内容后,内容放置在列表的哪个位置,由insetPolicy()对应值决定。
(2)与addItem无关,addItem方法固定将文本添加到最后。
2. SizeAdjustPolicy、minimumContentsLength()、setMinimumContentsLength()
(1)如果用resize设置了控件尺寸,此功能无效。
(2)Combobox默认值为AdjustToContentsOnFirstShow。
(3)AdjustToContentsOnFirstShow和AdjustToMinimumContentsLengthWithIcon均需要在可编辑模式下使用,才能达到预期效果(如果想使用这两种策略,但又不希望用户真的通过编辑文本框增加项目,可以在设置可编辑模式后,增加一行代码:combobox.lineEdit().setReadOnly(True));另外,对于AdjustToContentsOnFirstShow,一定要确保在展示控件前,就已经添加了内容,AdjustToMinimumContentsLengthWithIcon则无此要求。
(4)SizeAdjustPolicy策略是ComboBox独有的。
效果说明
(1)非可编辑模式,展示控件前已经添加了很多内容,但AdjustToContentsOnFirstShow模式 和AdjustToMinimumContentsLengthWithIcon模式下的宽度都没有达到预期效果:
(2)将前两个控件改为可编辑模式,控件宽度改变,最长的一项也能完整显示,下图中minimumContentsLength()值为0,因而前两个控件宽度相同。
(3)针对第2个控件(AdjustToMinimumContentsLengthWithIcon模式),设置setMinimumContentsLength(30),其宽度明显增加。
(4)控件已经完成展示,又添加了一个很长的内容,AdjustToContents模式能自动调整控件长度,将这个更长的内容完整显示,另外两种模式下,控件宽度保持原状。
3. setDuplicatesEnabled()、duplicatesEnabled()
(1) 仅针对可编辑模式下,用户从文本框输入的内容,对addItem添加的内容无效
(2) 如果想在使用addItem时,自动过滤已经添加过的项目,建议重写addItem方法。
4. addItem()、insertItem()等命令中,itemData及UserRole的含义
(1)UserRole
在combobox的使用中,UserRole可以用于存储每个item的额外信息(如用户信息:性别、年龄),它可以用来存储任何类型的数据,比如字符串、数字、对象等
(2)示例
代码
def about_add_insert(self):
self.combobox0.resize(200, 30)
self.combobox0.addItem('add-1', 'dataA of add-1')
self.combobox0.setItemData(0, 'dataB of add-1', 3)
self.combobox0.setItemData(0, QIcon('C.PNG'), 1)
self.label0.setText('data-role')
self.lineedit0.setText(self.combobox0.itemData(0)) # UserRole
self.label1.setText('data-role=3 ')
self.lineedit1.setText(self.combobox0.itemData(0, 3))
self.label2.setText('data-role=2')
self.lineedit2.setText(self.combobox0.itemData(0, 2))
效果:
(1)用AddItem添加选项时,设置了UserRole对应的数据为‘dataA of add-1‘,因而通过itemData(0)获取的,就是这一条用户信息;
(2)添加选项时没有用QIcon,因为设置DataRole=1(DecorationRole)的数据,出现了图片;
(3)通过设置DataRole=3(ToolTipRole)对应的内容为‘dataB of add 1‘,下方出现了提示框信息;
(4)DataRole=2对应的数据,就是文本框内容,如果通过setItemData修改EditRole(DataRole=2)的内容,这个项目的内容也会随之改变。