本文转自:《Qt编程指南》 作者:奇先生
Qt编程指南,Qt新手教程,Qt Programming Guide
8.1.1 QListWidget
在 Qt 设计师,左边的控件工具箱可以看到本章三个基于条目控件:
QListWidget 的基类是 QListView 视图类,关于基类的内容本节不介绍,等到模型视图章节再讲,本节只关注 QListWidget 本身的函数。
QListWidget 的构造函数很简单:
QListWidget(QWidget * parent = 0)
parent 是父窗口指针,如果用设计师拖控件,一般也不用手动调用构造函数。QListWidget 主要的函数是围绕条目添加、删除、选中条目、显示模式等功能以及相关的信号和槽,下面大致对这些功能函数分类来讲解:
(1)添加条目的函数
void QListWidget::addItem(QListWidgetItem * item)
这个添加函数需要实现 new 一个 QListWidgetItem 条目对象,然后添加到列表控件末尾,下面小节会专门讲 QListWidgetItem 类。
void QListWidget::addItem(const QString & label)
这第二个添加函数其实更常用,因为更简便,功能是将字符串 label 添加到列表控件末尾显示,其实该函数内部会自动根据字符串 new 一个条目对象添加到列表控件。
如果有设置好的字符串列表,那么可以通过如下函数把多个字符串全部添加到列表控件:
void QListWidget::addItems(const QStringList & labels)
add* 函数是将条目添加到末尾,如果要将条目插入到指定行 row 位置,则使用 insert* 函数:
void QListWidget::insertItem(int row, QListWidgetItem * item) //插入条目到第 row 行
void QListWidget::insertItem(int row, const QString & label) //插入字符串到第 row 行
void QListWidget::insertItems(int row, const QStringList & labels) //插入多个字符串到从 row 行开始的多个行。
获取列表控件里面的条目计数使用如下函数:
int QListWidget::count() const
(2)删除函数
因为是基于条目的控件,所以列表控件的删除单个条目函数名字是 takeItem():
QListWidgetItem * QListWidget::takeItem(int row)
takeItem() 根据行号从列表控件移除一个条目,并返回该条目指针,如果行号不合法,返回 NULL 指针。
如果返回的是实际存在的条目,那么需要注意,返回的条目指针需要手动 delete 掉,因为列表控件不再拥有该条目,该条目不会由列表控件析构时自动删除。
takeItem() 函数还有第二个用途,因为列表控件没有直接的调整条目前后顺序的函数,可以先将要调整顺序的条目移出来takeItem(),然后再调用 insertItem() 把这个条目插入到新的位置。
如果要清空整个列表控件,删除之前添加的所有条目,可以调用槽函数:
void QListWidget::clear()
(3)条目访问函数
根据行号获取条目对象的指针,使用如下函数:
QListWidgetItem * QListWidget::item(int row) const
如果已知列表控件含有的条目对象指针,反查当前行号,使用如下函数:
int QListWidget::row(const QListWidgetItem * item) const
在图形界面,如果希望根据列表控件在屏幕显示的相对坐标位置(以列表控件内部左上角为原点)来获取条目,使用如下函数:
QListWidgetItem * QListWidget::itemAt(const QPoint & p) const
QListWidgetItem * QListWidget::itemAt(int x, int y) const
反过来,如果根据已知条目,获取这个条目占据的矩形区域,使用如下函数:
QRect QListWidget::visualItemRect(const QListWidgetItem * item) const
(4)当前选中条目的操作
获取列表控件当前选中条目的函数如下:
QListWidgetItem * QListWidget::currentItem() const //当前选中 条目
int QListWidget::currentRow() const //当前选中的行号
如果当前没有选中的条目,那么返回的指针为 NULL,返回的序号为 -1 ,代码里要注意判断返回值。
设置已存在的某个条目为选中状态,使用函数:
void QListWidget::setCurrentItem(QListWidgetItem * item) //设置当前选中条目为 item
void QListWidget::setCurrentItem(QListWidgetItem * item, QItemSelectionModel::SelectionFlags command)
void QListWidget::setCurrentRow(int row, QItemSelectionModel::SelectionFlags command)//设置当前选中行为 row
void QListWidget::setCurrentItem(QListWidgetItem * item, QItemSelectionModel::SelectionFlags command)
第二个和第四个设置函数有个 SelectionFlags 类型的参数 command,这个参数决定选中的方式,是要选中QItemSelectionModel::Select ,还是取消选中 QItemSelectionModel::Deselect,还有其他选中方式,等到表格控件一节再详细列出来。
如果当前选中的条目发生变化,会触发如下三个信号,可以根据实际用途选择合适的信号:
void QListWidget::currentItemChanged(QListWidgetItem * current, QListWidgetItem * previous)
void QListWidget::currentRowChanged(int currentRow)
void QListWidget::currentTextChanged(const QString & currentText)
注意参数里的指针有可能为空值,序号可能为 -1,字符串也可能是空串,一定要注意判断非法的参数值。
本章的三个控件都可以设置选中模式,比如单选模式,一次只能选中一个条目,多选模式,一次可以选中多个条目等等,详细的选中模式在放到表格控件一节讲解,因为表格 中涉及的选中模式较多,一块讲解。本节的列表控件默认情况下,选中模式为单选 。QAbstractItemView::SingleSelection,以上的 *current* 等函数都是基于默认的单选模式的。
如果需要用到多选模式,可以设置 selectionMode 属性为 QAbstractItemView::ExtendedSelection,这种扩展选中模式类似常见的文件资源管理器的选中模式,可以使用 Ctrl 或 Shift 加鼠标点击实现多选:
void setSelectionMode(QAbstractItemView::SelectionMode mode) //设置选中模式
QAbstractItemView::SelectionMode selectionMode() const //获取选中模式
QAbstractItemView 是本章所有控件的抽象基类,本章后面控件也有类似的选中模式设置,如果把列表控件设置成多选模式,那么可以用如下函数获取同 时选中的多个条目:
QList<QListWidgetItem *> QListWidget::selectedItems() const
不论单选还是多选模式,条目选中情况有任何变化时,会触发如下信号:
void QListWidget::itemSelectionChanged()
(5)条目查找和排序
如果需要根据文本查找匹配的条目,使用如下函数:
QList<QListWidgetItem *> QListWidget::findItems(const QString & text, Qt::MatchFlags flags) const
该函数第一个参数 text 是要查找的模板子串,第二个参数是匹配标志,Qt::MatchFlags 是非常通用的枚举类型,不仅可用于字符串匹配,还能用于其他类型变量的匹配,Qt::MatchFlags 包含关于查找匹配的多种方式的枚举值:
Qt::MatchFlags 枚举常量 | 数值 | 描述 |
Qt::MatchExactly | 0 | 精确匹配,执行基于 QVariant 的匹配。 |
Qt::MatchFixedString | 8 | 执行基于字符串的匹配,如果不指定 MatchCaseSensitive,默认是大小写不敏感。 |
Qt::MatchContains | 1 | 条目包含要查找的模板子串。 |
Qt::MatchStartsWith | 2 | 条目以要查找的模板子串打头。 |
Qt::MatchEndsWith | 3 | 条目以要查找的模板子串结尾。 |
Qt::MatchCaseSensitive | 16 | 查找时大小写敏感。 |
Qt::MatchRegExp | 4 | 根据正则表达式模板子串匹配字符串。 |
Qt::MatchWildcard | 5 | 根据通配符模板子串(如 *.txt)匹配字符串。 |
Qt::MatchWrap | 32 | 执行回绕查找,当查找到最后一个条目时返回到第一个的条目继续查找,直到所有的条目都检查一遍。 |
Qt::MatchRecursive | 64 | 递归查找,遍历所有子条目。 |
后面两节的表格控件和树形控件也有类似的查找函数 findItems() ,第二个匹配标志参数也是一样的类型。
列表控件的自动排序是通过 sortingEnabled 属性来控制,获取和设置函数如下:
bool isSortingEnabled() const
void setSortingEnabled(bool enable)
列表控件条目默认是不排序的,如果希望自动按照字典序排序,调用 setSortingEnabled(true) 即可。另外还可以手动对列表控件现有条目排序:
void QListWidget::sortItems(Qt::SortOrder order = Qt::AscendingOrder)
Qt::AscendingOrder 是按升序排列,Qt::DescendingOrder 是按降序排列。
(6)条目显示和运行时条目编辑
关于列表控件 QListWidget 和里面的条目 QListWidgetItem,需要注意条目 QListWidgetItem 仅仅是数据,不是控件或子控件,列表控件根据多个 QListWidgetItem 对象,来呈现条目里的数据,只有列表控件自己是控件实体。
列表控件默认以自己的方式呈现条目数据,比如白底黑字的普通条目显示,如果要按照特殊的子控件来显示字符串,比如用 QLabel 对象显示条目数据,可以用如下函 数:
void QListWidget::setItemWidget(QListWidgetItem * item, QWidget * widget)
列表控件会同时拥有 item 数据条目和用于显示 item 的子控件 widget。注意这里的子控件 widget 只有静态显示功能,如果用按钮作为显示子控件,那么按钮是不可点击的。如果希望自己定制一个能交互操作的子条目显示控件,需要使用 QListView 并子类化 QItemDelegate 类,这些复杂的等到模型视图章节再讲。
对于本节列表控件,如果要获取 setItemWidget() 函数指定某个条目的显示子控件,使用如下函数:
QWidget * QListWidget::itemWidget(QListWidgetItem * item) const
如果要删除上面 setItemWidget() 指定的特殊显示控件,使用函数:
void QListWidget::removeItemWidget(QListWidgetItem * item)
特殊的显示子控件移除后,该条目就还按照列表控件原来的普通条目显示。
如果希望在程序运行时编辑列表控件的条目,有两种方式,本小节先讲第一种(第二种是设置条目自身的特性标志),手动打开条目的文本编辑器(这个编辑器是列表控件自 带功能,与 setItemWidget 设置的显示子控件没关系):
void QListWidget::openPersistentEditor(QListWidgetItem * item)
这个函数名是打开条目的持续编辑器,持续的意思是如果不调用关闭函数,该条目的编辑器会一直开启,关闭这个持续编辑器使用如下函数:
void QListWidget::closePersistentEditor(QListWidgetItem * item)
一般可以在检测到条目激活信号(itemActivated)时调用打开函数 openPersistentEditor() ,在当前条目变化( currentItemChanged)时调用关闭函数 closePersistentEditor() 。 使用这一对开关持续编辑器函数涉及到编写多个信号的槽函数,使用比较麻烦,建议用后面第二小节介绍的条目标 志位和 QListWidget::editItem(QListWidgetItem * item) 实现条目的可编辑功能。
(7)其他信号和槽函数
除了上面关于当前条目变化和选中条目变化的信号,条目还有激活、单击、双击等信号,罗列如下:
void QListWidget::itemActivated(QListWidgetItem * item) //激活信号
当用户点击或双击条目时,条目会被激活,具体哪些操作会激活条目,要根据操作系统设置来定,比如 Windows 一般是双击打开激活,KDE 桌面通常是单击打开激活。另外,系统的快捷键也可以激活条目,如 Windows 和 Linux X11 桌面是回车键激活,Mac OS X 是 Ctrl+0 ,一般激活信号用于开启编辑等操作。
void QListWidget::itemChanged(QListWidgetItem * item) //条目内容发生变化
注意这是条目内容变化的信号,不是选中状态变化,程序如果在运行时改变了条目文本内容,比如持续编辑器修改了文本,会触发这个信号。
剩下几个单击、双击、进入、按压等信号意义比较直白,不详细解释了:
void QListWidget::itemClicked(QListWidgetItem * item) //条目单击信号
void QListWidget::itemDoubleClicked(QListWidgetItem * item) //条目双击信号
void QListWidget::itemEntered(QListWidgetItem * item) //鼠标追踪时进入条目的信号,一般用不着
void QListWidget::itemPressed(QListWidgetItem * item) //鼠标按键在条目上处于按下状态时发的信号
列表控件的槽函数除了前面讲过的 clear() 槽函数用于清空所有条目,还有个比较实用的条目滚动函数,列表控件自带滚动条,当条目总数超出控件矩形能呈现的数目时,滚动条自动出现,通过滚动条支持更多的条目显示。使 用如下槽函数可 以让列表控件滚动到想显示的某个条目位置:
void QListWidget::scrollToItem(const QListWidgetItem * item, QAbstractItemView::ScrollHint hint = EnsureVisible)
第一个参数 item 就是想显示出来的条目,第二个参数是滚动显示方式,默认是 QAbstractItemView::EnsureVisible,即保证指定条目显示出来,还有其他的滚动显示方式:
QAbstractItemView::ScrollHint 枚举常量 | 数值 | 描述 |
QAbstractItemView::EnsureVisible | 0 | 滚动到指定条目能显示出来即可。 |
QAbstractItemView::PositionAtTop | 1 | 滚动直到将指定条目显示到可视区域的顶部。 |
QAbstractItemView::PositionAtBottom | 2 | 滚动直到将指定条目显示到可视区域的底部。 |
QAbstractItemView::PositionAtCenter | 3 | 滚动直到将指定条目显示到可视区域的中间。 |