Qt系列教程总目录
组合框 QComboBox
即我们常用的下拉列表,如下是一些使用示例:
office word 中的字体字号设置、段落设置等,很普遍的使用了类似 QComboBox
的下拉列表。
QComboBox
不仅可以用于多选项选择,还节省屏幕空间。
他只有一个构造函数
QComboBox(QWidget *parent = nullptr);
使用时一般传入父级窗口对象指针。
QComboBox
可以看做是一个类似列表的容器,列表每一项是一个item
对象,该对象有类似 Map
的成员,Map
包含类似text
、icon
等key
,并在value
域存储对应的数据。
对于 key
,Qt有自己的枚举定义,如下:
enum ItemDataRole {
DisplayRole = 0,
DecorationRole = 1,
EditRole = 2,
ToolTipRole = 3,
StatusTipRole = 4,
WhatsThisRole = 5,
// Metadata
FontRole = 6,
TextAlignmentRole = 7,
BackgroundRole = 8,
ForegroundRole = 9,
CheckStateRole = 10,
// Accessibility
AccessibleTextRole = 11,
AccessibleDescriptionRole = 12,
// More general purpose
SizeHintRole = 13,
InitialSortOrderRole = 14,
// Internal UiLib roles. Start worrying when public roles go that high.
DisplayPropertyRole = 27,
DecorationPropertyRole = 28,
ToolTipPropertyRole = 29,
StatusTipPropertyRole = 30,
WhatsThisPropertyRole = 31,
// Reserved
UserRole = 0x0100
};
枚举说明如下:
常量 | 值 | 描述 | value的数据类型 |
---|---|---|---|
Qt::DisplayRole | 0 | 要以文本形式呈现的数据 | QString |
Qt::DecorationRole | 1 | 要以图标形式呈现的数据 | QColor/QIcon/QPixmap |
Qt::EditRole | 2 | 适合在编辑器中编辑的数据 | QString |
Qt::ToolTipRole | 3 | 显示在item的工具提示中的数据 | QString |
Qt::StatusTipRole | 4 | 状态栏中显示的数据 | QString |
Qt::WhatsThisRole | 5 | 显示在项目的“what is this?”模式下的数据 | QString |
Qt::FontRole | 6 | item的默认字体 | QFont |
Qt::TextAlignmentRole | 7 | item的文本对齐方式 | Qt::Alignment |
Qt::BackgroundRole | 8 | item的背景笔刷 | QBrush |
Qt::ForegroundRole | 9 | item的前景笔刷(通常为文本颜色) | QBrush |
Qt::CheckStateRole | 10 | 用于获取item的已检查状态 | Qt::CheckState |
Qt::AccessibleTextRole | 11 | 可访问性扩展和插件(如屏幕阅读器)要使用的文本 | QString |
Qt::AccessibleDescriptionRole | 12 | 出于可访问性目的对item的描述 | QString |
Qt::SizeHintRole | 13 | 提供给视图的项目的建议尺寸 | QSize |
Qt::InitialSortOrderRole | 14 | 获取页眉视图部分的初始排序顺序(Qt 4.8引入) | Qt::SortOrder |
Qt::DisplayPropertyRole | 27 | Qt内部使用 | - |
Qt::DecorationPropertyRole | 28 | Qt内部使用 | - |
Qt::ToolTipPropertyRole | 29 | Qt内部使用 | - |
Qt::StatusTipPropertyRole | 30 | Qt内部使用 | - |
Qt::WhatsThisPropertyRole | 31 | Qt内部使用 | - |
Qt::UserRole | 0x0100 | 存储用户数据 | 由用户决定使用哪些类型,并确保组件在访问和设置数据时使用正确的类型 |
void addItem(const QString &text, const QVariant &userData = QVariant());
void addItem(const QIcon &icon, const QString &text,
const QVariant &userData = QVariant());
void addItems(const QStringList &texts){ insertItems(count(), texts); }
该函数在列表的末尾添加item
,其中userData
是用户数据,用户可以把 QComboBox
作为选择列表使用,也可以看作是类似 Map
的存储容器,在选择时操作用户自定义数据。
void insertItem(int index, const QString &text, const QVariant &userData = QVariant());
void insertItem(int index, const QIcon &icon, const QString &text,
const QVariant &userData = QVariant());
void insertItems(int index, const QStringList &texts);
通过指定索引插入 item
。
void removeItem(int index);
通过指定索引删除 item
。
void setItemText(int index, const QString &text); // 设置item的文本
void setItemIcon(int index, const QIcon &icon); // 设置item的图标
void setIconSize(const QSize &size); // 设置item的图标尺寸
// 设置item的用户数据
void setItemData(int index, const QVariant &value, int role = Qt::UserRole);
void setMaxCount(int max); // 设置item的允许最大数量
QString itemText(int index) const; // 获取item的文本
QIcon itemIcon(int index) const; // 获取item的图标
QSize iconSize() const; // 获取item的图标尺寸
QVariant itemData(int index, int role = Qt::UserRole) const; // 获取item的用户数据
int count() const; // 获取item的数量
int maxCount() const; // 获取item的允许最大数量
int currentIndex() const;
QString currentText() const;
QVariant currentData(int role = Qt::UserRole) const;
获取当前选择的 item
的文本、图标和用户数据。
bool isEditable() const;
void setEditable(bool editable);
下拉列表不仅可供选择,也可以让用户输入列表中没有的选项(默认不可编辑),如下图:
另外还有一个函数也可以实现组合框可编辑:
void setLineEdit(QLineEdit *edit);
QLineEdit *lineEdit() const;
他将行编辑框的编辑权赋予组合框,实际上在函数setEditable
内部也调用了 setLineEdit
,如下:
int maxVisibleItems() const;
void setMaxVisibleItems(int maxItems);
一般情况下,下拉列表有多少 item
就会显示多少,如下:
如 item
过多,会显得不美观,可以通过该函数设置显示item的个数,如下设置最大显示个数为 5
,其余会隐藏在滚动条中:
关于这个函数有一个很迷的现象,官方文档有如下描述:
对于不可编辑的组合框,
QStyle::SH_ComboBox_Popup
返回true
,该属性将被忽略,例如Mac style
或Gtk+ Style
。然而,在
ubuntu
系统下,对于不可编辑的组合框,QStyle::SH_ComboBox_Popup
返回0
,该属性仍然未生效;在windows
系统下,对于不可编辑的组合框,QStyle::SH_ComboBox_Popup
返回0
,该属性生效。如你知道原因欢迎评论区留言。
有图有真相:
Ubuntu下:
Windows下:
该问题可以通过以下方法规避,即使该属性在 Ubuntu
系统中生效:
方法一:设置组合框可编辑,setEditable(true);
方法二:设置setStyleSheet("QComboBox{combobox-popup:0;}");
int count() const; // 当前存储的item个数
void setMaxCount(int max); // 设置允许存储的item最大个数
int maxCount() const; // 获取允许存储的item最大个数
如果设置的最大个数小于当前存储的个数,多余的item会被删除。
有时会在组合框中添加重复的项,如下:
有两种方式添加重复项,一种是通过代码(Qt总是允许通过代码添加重复项),如下:
ui->comboBox->addItem("item1");
ui->comboBox->addItem("item2");
ui->comboBox->addItem("item3");
ui->comboBox->addItem("item4");
ui->comboBox->addItem("item4");
第二种是用户编辑输入,但Qt默认不允许这种方式,需要设置属性:
bool duplicatesEnabled() const;
void setDuplicatesEnabled(bool enable);
void setFrame(bool);
bool hasFrame() const;
// 通过text查找
inline int findText(const QString &text, Qt::MatchFlags flags = static_cast<Qt::MatchFlags>(Qt::MatchExactly|Qt::MatchCaseSensitive)) const
{ return findData(text, Qt::DisplayRole, flags); }
// 通过data查找
int findData(const QVariant &data, int role = Qt::UserRole, Qt::MatchFlags flags = static_cast<Qt::MatchFlags>(Qt::MatchExactly|Qt::MatchCaseSensitive)) const;
可以发现 findText
也是通过 findData
实现的,所以对于其他属性的搜索,我们也可以通过 findData
实现,因为 findData
的 data
参数是通用类型,使用时只需指定相应的 role
即可(role枚举见ItemDataRole
)。
第三个参数 flags
定义了匹配方式,Qt::MatchFlags
枚举如下:
enum MatchFlag {
MatchExactly = 0,
MatchContains = 1,
MatchStartsWith = 2,
MatchEndsWith = 3,
MatchRegularExpression = 4,
MatchWildcard = 5,
MatchFixedString = 8,
MatchTypeMask = 0x0F,
MatchCaseSensitive = 16,
MatchWrap = 32,
MatchRecursive = 64
};
枚举成员描述如下:
常量 | 值 | 描述 |
---|---|---|
Qt::MatchExactly | 0 | 搜索词与item的完全匹配 |
Qt::MatchContains | 1 | 搜索词包含在item中 |
Qt::MatchStartsWith | 2 | 搜索词与item的开头匹配 |
Qt::MatchEndsWith | 3 | 搜索词与item的结尾匹配 |
Qt::MatchRegularExpression | 4 | 使用正则表达式作为搜索项执行基于字符串的匹配。 |
Qt::MatchWildcard | 5 | 使用带有通配符的字符串作为搜索词,执行基于字符串的匹配。 |
Qt::MatchFixedString | 8 | 执行基于字符串的匹配。除非同时指定MatchCaseSensitive标志,否则基于字符串的比较不区分大小写。 |
Qt::MatchCaseSensitive | 16 | 搜索区分大小写。 |
Qt::MatchWrap | 32 | 执行一个环绕的搜索,这样,当搜索到达模型中的最后一个项目时,它会从第一个项目开始,并一直持续到检查完所有项目为止。 |
MatchRecursive | 64 | 搜索整个层次结构。 |
注意:Qt::MatchExamplete
、Qt::MatchContains
、Qt::MatchStartsWith
、Qt::MatchEndsWith
,Qt::MatchRegularExpression
、Qt::MatchWildcard
和 Qt::MatchFixedString
是互斥的,Qt还不支持通过 Qt::MatchFlags
参数同时设置多个。
当组合框可编辑,用户可以通过手动输入来添加item
,这时新的item
插入到哪里,由枚举 InsertPolicy
指定,默认为 InsertAtBottom
在下方新增,使用如下方法设置插入策略:
InsertPolicy insertPolicy() const;
void setInsertPolicy(InsertPolicy policy);
InsertPolicy
枚举如下:
enum InsertPolicy {
NoInsert,
InsertAtTop,
InsertAtCurrent,
InsertAtBottom,
InsertAfterCurrent,
InsertBeforeCurrent,
InsertAlphabetically
};
说明如下:
常量 | 值 | 描述 |
---|---|---|
QComboBox::NoInsert | 0 | 字符串不会插入到组合框中 |
QComboBox::InsertAtTop | 1 | 字符串会被插入到组合框的第一个位置 |
QComboBox::InsertAtCurrent | 2 | 当前选择的item会被新的字符串覆盖 |
QComboBox::InsertAtBottom | 3 | 字符串会被插入到组合框的最后一个位置 |
QComboBox::InsertAfterCurrent | 4 | 字符串会被插入到当前选择的后一个位置 |
QComboBox::InsertBeforeCurrent | 5 | 字符串会被插入到当前选择的前一个位置 |
QComboBox::InsertAlphabetically | 6 | 字符串按字母顺序插入组合框中 |
由于不同item
的内容长度不同,组合框的大小调整会有一定策略,默认 AdjustToContentsOnFirstShow
,使用如下函数设置该策略:
SizeAdjustPolicy sizeAdjustPolicy() const;
void setSizeAdjustPolicy(SizeAdjustPolicy policy);
策略枚举如下:
enum SizeAdjustPolicy {
AdjustToContents,
AdjustToContentsOnFirstShow,
AdjustToMinimumContentsLengthWithIcon
};
说明如下:
常量 | 值 | 描述 |
---|---|---|
QComboBox::AdjustToContents | 0 | 始终根据item内容进行调整,以使其全部显示 |
QComboBox::AdjustToContentsOnFirstShow | 1 | 组合框将在第一次显示时根据item内容进行调整 |
QComboBox::AdjustToMinimumContentsLengthWithIcon | 2 | 组合框将调整为最小内容长度加上图标空间。使用该策略,需要考虑性能问题 |
其中MinimumContentsLength
和iconSize
都可以另外设置,方法如下:
int minimumContentsLength() const; // 默认为0
void setMinimumContentsLength(int characters);
QSize iconSize() const;
void setIconSize(const QSize &size);
当组合框没有任何 item
时,可以添加占位符文本,以使组合框显示不为空,如下:
当然,占位符是灰色的不可被选择的。
方法接口如下:
void setPlaceholderText(const QString &placeholderText);
QString placeholderText() const;
组合框除了显示为下拉列表,也可以显示自定义的数据模型,比如树或表格,相关方法如下:
QAbstractItemModel *model() const;
virtual void setModel(QAbstractItemModel *model); // 将自定义的数据模型添加到组合框
QModelIndex rootModelIndex() const;
void setRootModelIndex(const QModelIndex &index); // 设置项目的根模型项目索引
int modelColumn() const;
// 设置模型可见列。如果在填充组合框之前设置,则视图不受影响,将显示第一列(使用此属性的默认值0)。
void setModelColumn(int visibleColumn);