列表控件可以让我们以列表形式呈现内容,使界面更加有序美观。QListWidget列表控件应当与QListWidgetItem一起使用,后者作为项被添加入列表控件中,也就是说列表控件中的每一项都是一个QListWidgetItem。这也是为什么我们说QListWidget是一个基于项(Item-based)的控件了。
同样基于项的控件还有QTreeWidget树形控件和QTableWidget表格控件,前者以树状方式呈现内容,并与QTreeWidgetItem搭配使用;后者以表格形式呈现内容,并与QTableWidgetItem一起使用。
19.1 列表控件QListWidget
笔者曾经做了一个可以方便生成报价表的桌面小程序,截图如下:
程序中就用到了QListWidget,当选择一种产品系列后,左边的列表空间就会显示该系列的所有内容,然后双击其中的某项就可以在右边的列表控件中显示所双击的项:
我们就通过实现这个简单的功能来学习下QListWidget。
import
1. pic_label用于显示图片;
2. 实例化两个QListWidget,listwidget_1放在左边用于显示可选的内容,listwidget_2放在右边用于显示被双击的项。然后将这两个QListWidget控件的doubleClicked信号和自定义的槽函数连接起来,每当双击QListWidget中的某项时,就会触发该槽函数。
3. 循环创建六个QListWidgetItem,并通过调用addItem(QListWidgetItem)将其添加到listwidget_1中;
4. 当然也可以通过实例化时直接指定父类的方式进行添加;
5. 也可以不用QListWidgetItem,直接调用addItem(str)方法来添加一项内容。也可以使用addItem(Iterable)来添加一组项内容(不过若要让项呈现更多功能的话,还是应该选择QListWidgetItem);
6. 通过insertItem(row, QListWidgetItem)方法可以在指定行中加入一项内容;
7. 接下来我们讲一下槽函数:
def
在槽函数中,我们判断信号是哪一个QListWidget发出的,如果是listwidget_1的话,我们先通过currentItem()获取到当前被双击的项,之后实例化为QListWidgetItem,再通过addItem(QListWidgetItem)方法加入listwidget_2中,count()方法用于获取项数量,这里我们打印出listwidget_2中一共有多少项内容。若信号是listwidget_2发出的话,则将当前被双击项的行数传给takeItem(int)方法来进行删除,然后也打印下项数量。
bug report:currentItem()的返回值是QListWidgetItem,照理来说应该是可以直接被添加的,也就是说下方这种写法应该也是可以的,但是却没有用:
self
图片下载地址:
arrow.png: https://www.easyicon.net/download/png/3980/64/
运行截图如下,双击左边的某项,会发现右边的列表控件会显示出来:
双击右边的某项将其删除:
19.2 树形控件QTreeWidget
通常我们用QTreeWIdget来显示文件目录结构,比如下图:
但这里我们将用QTreeWidget实现在第七章讲解QCheckBox按钮时展示的安装程序树状结构:
我们取以下部分进行说明并实现:
可以看出根节点为Preview,其子节点为Qt5.11.2 snapshot,它一共有三种状态:全选中、无选中和半选中。而该子节点下面又有macOS、Android x86、Android ARMv7、Sources和iOS子节点。
下面开始实现,请看代码:
import
1. QLabel控件用于显示每个QTreeWidgetItem的文本;
2. 实例化一个QTreeWidget,通过setColumnCount(int)将该树状控件的列数设为2(默认为1列)。通过setHeaderLabels(Iterable)设置每列的标题,如果只有一列的话,则应该通过setHeaderLabel(str)方法设置。接着我们将itemClicked信号与自定义的槽函数连接起来,每当点击QTreeWidget中的任意一项时,都会触发itemClicked信号。QtAssistant中对该信号的说明如下:
我们发现这是一个带参数的信号,而文档中解释说:每当一项内容被点击时,参数item就是被点击的项,参数column就是被点击项所在的列。也就是说当该信号被触发时,参数item保存被点击的项,column保存列数,而这两个参数会自动传给我们的槽函数。为与之对应,我们的槽函数也带了两个参数,这样我们就可以知道被点击的项和列数了。
3. 实例化一个QTreeWidgetItem,并将其父类设为self.tree,表示self.preview为最外层(最顶层)的项,接着通过setText(int, str)方法来设置文本,第一个int类型参数为该文本所在的列,0表示放在第一列。当然我们也可以在实例化时不指定父类,并让self.tree调用addTopLevelItem()方法来设置最顶层的项;
4. setCheckState(int, CheckState)方法可以让该项以复选框形式呈现出来,addChild(QTreeWidgetItem)方法可以添加子项,这里让self.preview添加一个self.qt5112选项;
5. 实例化5个子项,将他们添加到self.qt5112中,并以复选框形式显示;
6. 这里的self.test项只是拿来作为对比,好让读者知道将QTreeWidget设为两列时的样子;
7. 调用expandAll()方法可以让QTreeWidget所有的项都是以打开状态显示的。注意必须要在所有项都已经实例化好之后再调用该方法,如果一开始就调用则会没有效果;
8. 在槽函数中,self.label显示对应的项文本,item就是被点击的项,我们调用text(int)传入列数,获得文本(该text()函数用法跟我们之前使用的有所不同)。
9. 如果被点击的项为qt5112,则我们判断是否其被选中,若是的话,将它的所有子项都设为选中状态,若为无选中状态的话,则将其子项全部设为无选中状态;
10. 若被点击是qt5112的子项时,我们判断有多少个子项已经被选中了,若数量为5,则设置qt5112为选中状态,若为0-5之间,则设为半选中状态,若等于0,则设为无选中状态。
运行截图如下:
19.3 表格控件QTableWidget
核心都是类似的,搭配QTableWidgetItem使用,下面就来讲一下常用的方法:
import
1. 这里我们直接继承QTableWidget来实现程序;
2. setRowCount(int)设置表格的行数,setColumnCount(int)设置列数。或者可以选择在实例化的时候直接指定行列数;
3. rowCount()获取行数,columnCount()获取列数;
4. setColumnWidth(int, int)设置列款,第一个参数填列序号,第二个参数填宽度值。setRowCount(int, int)设置行宽,参数同理;
5. setHorizontalHeaderLabels(iterable)设置行的标题,而setVerticalHeaderLabels设置列的标题;
6. setShowGird(bool)设置是否显示表格上的网格线,True为显示,False不显示;
7. 实例化一个单元格,并用setItem(int, int, QTableWidgetItem)将该单元格添加到表格中。前两个int类型参数分别为行序号和列序号;
8. setTextAlignment()设置单元格的文本对齐方式,QtAssistant中输入Qt::Alignment就可以找到各种对齐方式:
9. setSpan(int, int, int, int)方法用来合并单元格,前两个int参数分别为行序号和列序号,后两个分别为要合并的行数和列数;
10. findItems(str, Qt.MatchFlag)方法用来进行查找,前一个参数为用来匹配的字符串,后一个参数为匹配方式。在代码中我们用了两种匹配方式,第一种为Qt.MatchExactly,表示精确匹配。第二种为Qt.MatchContains,表示包含匹配。在QtAssistant中输出Qt::MatchFlag即可了解各种匹配方式:
运行截图如下:
若要更加个性化地控制界面,请大家阅读:
《PyQt5高级编程实战》学会使用视图委托_la_vie_est_belle的博客-CSDN博客pyqt5.blog.csdn.net19.4 小结
1. 列表控件QListWidget,树状控件QTreeWidget以及表格控件QTableWidget这三种控件都是基于项(item-based)的控件,应搭配QListWidgetItem,QTreeWidgetItem和QTableWidgetItem使用;
2. 多使用文档。