PyQt6 基础操作:下拉列表框 QComboBox (Part1)

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方法固定将文本添加到最后。

9797d43047bc0f0dc64a5ddf2f9b5eeb.png

346d637e28675b09f661a63a63703d9f.png

 2. SizeAdjustPolicy、minimumContentsLength()、setMinimumContentsLength()

(1)如果用resize设置了控件尺寸,此功能无效。

(2)Combobox默认值为AdjustToContentsOnFirstShow。

(3)AdjustToContentsOnFirstShow和AdjustToMinimumContentsLengthWithIcon均需要在可编辑模式下使用,才能达到预期效果(如果想使用这两种策略,但又不希望用户真的通过编辑文本框增加项目,可以在设置可编辑模式后,增加一行代码:combobox.lineEdit().setReadOnly(True));另外,对于AdjustToContentsOnFirstShow,一定要确保在展示控件前,就已经添加了内容,AdjustToMinimumContentsLengthWithIcon则无此要求。

(4)SizeAdjustPolicy策略是ComboBox独有的。

效果说明

(1)非可编辑模式,展示控件前已经添加了很多内容,但AdjustToContentsOnFirstShow模式 和AdjustToMinimumContentsLengthWithIcon模式下的宽度都没有达到预期效果:

03403e996f7d8ad8da22327ebb9384bf.png

(2)将前两个控件改为可编辑模式,控件宽度改变,最长的一项也能完整显示,下图中minimumContentsLength()值为0,因而前两个控件宽度相同。

9f1437ad32c6ef342fb32f7bc95c56ba.png

(3)针对第2个控件(AdjustToMinimumContentsLengthWithIcon模式),设置setMinimumContentsLength(30),其宽度明显增加。

c19b9acce9eedfb6f805cd6a1699f961.png

(4)控件已经完成展示,又添加了一个很长的内容,AdjustToContents模式能自动调整控件长度,将这个更长的内容完整显示,另外两种模式下,控件宽度保持原状。

be4a63ef130dc40651140c17fafd4885.png

3. setDuplicatesEnabled()、duplicatesEnabled()

(1) 仅针对可编辑模式下,用户从文本框输入的内容,对addItem添加的内容无效

c40b5f2a489d6e7c4a014778ba771c8f.png

(2) 如果想在使用addItem时,自动过滤已经添加过的项目,建议重写addItem方法。

4. addItem()、insertItem()等命令中,itemData及UserRole的含义

(1)UserRole

在combobox的使用中,UserRole可以用于存储每个item的额外信息(如用户信息:性别、年龄),它可以用来存储任何类型的数据,比如字符串、数字、对象等

23a665126955b65f4a5e9dd824116735.png

d1335feaae81db099e9a99c20730daac.png

(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))

效果:

46bf5c8ec6b766634e7e15027cf3abd2.png

(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)的内容,这个项目的内容也会随之改变。

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值