PyQt5高级界而控件(表格与树)

表格与树解决的问题是如何在一个控件中有觌律地呈现更多的数据。PyQt提供
了两种控件类用于解决该问题,其中一种是表格结构的控件类:另一种是树形结构
的控件类。

QTableView

在通常情况下,一个应用需要和一批数据(比如数组、列表)进行交互,然后
以表格的形式输出这些信息,这时就要用到QTableView类了。在QtableView中可
以使用自定义的数据模型来显示内容,通过来绑定数据源。

QTableWidget继承自QTableView,主要区别是QTableView可以使用自定义的
数据模型来显示内容(先要通过setModel来绑定数据源),而QTableWidget只能使
用标准的数据模型,并且其单元格数据是通过QTableWidgetItem对象来实现的。通
常使用QTableWidget就能够满足我们的要求。

QTableView控件可以绑定一个模型数据用来更新控件上的内容,可用的模式如
表5-1所示。

方法描述
QStringListModel存储一组字符串
QStandardItemModel存储任意层次结的数据
QDirModel对文件系统进行封装
QSqlQueryModel对SQL的查询结果集进行封装
QSqlTableModel对SQL中的表格进行封装
QSqlRelationalTableModel对带有foreign key的SQL表格进行封装
QSortFilterProxyModel对模型中的数据进行排序或过滤
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys

class Table(QWidget):
    def __init__(self,arg=None):
        super(Table,self).__init__(arg)
        self.setWindowTitle("QTableView表格视图控件的例子")
        self.resize(500,300)
        self.model=QStandardItemModel(4,4)
        self.model.setHorizontalHeaderLabels(['标题','标题2','标题3','标题4'])

        for row in range(4):
            for column in range(4):
                item=QStandardItem("row %s,column %s"%(row,column))
                self.model.setItem(row,column,item)

        self.tableView = QTableView()
        self.tableView.setModel(self.model)
        #下面代码让表哥100填满窗口
        #self.tableView.horizontalHeader().setStretchLastSection(True)
        #self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

        dlgLayout = QVBoxLayout()
        dlgLayout.addWidget(self.tableView)
        self.setLayout(dlgLayout)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    table=Table()
    table.show()
    sys.exit(app.exec_())

QTabIeView的使用

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys

class Table(QWidget):
    def __init__(self,arg=None):
        super(Table,self).__init__(arg)
        self.setWindowTitle("QTableView表格视图控件的例子")
        self.resize(500,300)
        self.model=QStandardItemModel(4,4)
        self.model.setHorizontalHeaderLabels(['标题','标题2','标题3','标题4'])

        for row in range(4):
            for column in range(4):
                item=QStandardItem("row %s,column %s"%(row,column))
                self.model.setItem(row,column,item)

        self.tableView = QTableView()
        self.tableView.setModel(self.model)
        #下面代码让表哥100填满窗口
        #self.tableView.horizontalHeader().setStretchLastSection(True)
        #self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

        dlgLayout = QVBoxLayout()
        dlgLayout.addWidget(self.tableView)
        self.setLayout(dlgLayout)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    table=Table()
    table.show()
    sys.exit(app.exec_())

运行结果

image

从上图可以看出,表格并没有填满窗口,每列可以自由拉动,但是可能会出
现滚动条。

(1)需要表格填满窗口,可以添加下面代码。

self.tableView.horizontalHeader().setStretchLastSection(True)
self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

(2)添加数据。

self.model.appendRow([
        QStandardItem("row %s,column %s"%(11,11)),
        QStandardItem("row %s,column %s"%(11,12)),
        QStandardItem("row %s,column %s"%(11,13)),
        QStandardItem("row %s,column %s"%(11,14)),
    ])

(3)删除当前选中的数据。
第一种方法:

#取当前选中的所有行
    indexs=self.tableView.selectionModel().selection().indexes()
    if len(indexs)>0:
        #取第一行的索引
        index=indexs[0]
        self.model.removeRows(index.row(),1)

第二种方法:

 index=self.tableView.currentIndex()
    print(index.row())
    self.model.removeRow(index.row())

如果在表格中什么也不选,那么默认删除的是第一行,也就是索引为0的行:
选中一行时就删除这一行:选中多行时,如果焦点在最后一行,就删除这一行。

QListView

QListView类用于展示数据,它的子类是QListWidget。QListView是基于模型
(Model)的,需要程序来建立模型,然后再保存数据。

QListWidget是一个升级版本的QListView,它已经建立了一个数据存储模型
(QListWidgetItem),直接调用addltem()函数,就可以添加条目(ltem)。

QListView类中的常用方法如表5-2所示。

方法描述
setModel()用来设置View所关联的ModeI,可以使用Python原生的list作为数据源
Model
selectedItem()选中ModeI中的条目
isSelected()判断Model中的某条目是否被选中

QListView类中的常用信号如表5-3所示。

信号含义
clicked当单击某项时,信号被发射
doubleClicked当双击某项时,信号被发射

QListView的使用

from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QListWidget, QMessageBox, QListView
from PyQt5.QtCore import QStringListModel
import sys

class ListViewDemo(QWidget):
    def __init__(self,parent=None):
        super(ListViewDemo,self).__init__(parent)
        self.setWindowTitle("ListViewDemo")
        self.resize(300,270)
        layout = QVBoxLayout()

        listView = QListView()
        slm=QStringListModel()
        self.qList=['Item1','Item2','Item3','Item4']
        slm.setStringList(self.qList)
        listView.setModel(slm)
        listView.clicked.connect(self.clicked)
        layout.addWidget(listView)
        self.setLayout(layout)

    def clicked(self,qModelIndex):
        QMessageBox.information(self,"QListView","你选择了:"+self.qList[qModelIndex.row()])

if __name__ == '__main__':
    app = QApplication(sys.argv)
    win=ListViewDemo()
    win.show()
    sys.exit(app.exec_())

运行结果

image
运行脚本,显示效果如图5-3所示。
在这个例子中,当单击QListView控件里Model中的一项时会弹出消息框(提
示选择的是哪一项)。
将QListView控件的clicked信号与自定义对象的cIicked()槽函数进行绑定。

listView.clicked.connect(self.clicked)

QListWidget

QListWidet类是一个基于条目的接口,用于从列表中添加或删除条目。列表中
的每个条目都是一个QListWidgetItem对象。QListWidget可以设置为多重选择。
QListWidget类中的常用方法如表5-4所示。

方法描述
addItem()在列表中添加QListWidgetltem对象或字符串
addItems()添加列表中的每个条目
insertItem()在指定的索引处插入条目
clear()删除列表的内容
setCurrentItem()设置当前所选条目
sortItems()按升序重新排列条目

QListWidget类中的常用信号如表5-5所示。

信号含义
currentItemChanged当列表中的条目发生改变时发射此信号
itemClicked当点击列表中的条目时发射此信号

QListWidget的使用

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class ListWidget(QListWidget):
    def clicked(self, item):
        QMessageBox.information(self,"ListWidget","你选择了:"+item.text())

if __name__ == '__main__':
    app = QApplication(sys.argv)
    listWidget=ListWidget()
    listWidget.resize(300,120)
    listWidget.addItem("Item1")
    listWidget.addItem("Item2")
    listWidget.addItem("Item3")
    listWidget.addItem("Item4")
    listWidget.setWindowTitle('QListWidget 例子')
    listWidget.itemClicked.connect(listWidget.itemClicked)
    listWidget.show()
    sys.exit(app.exec_())

运行结果

image
代码分析:
在这个例了中,当单击QListWidget列表中的一个条目时会弹出消息框,提示
选择的是哪个条目。
将QListWidget控件的itemClicked信号与自定义对象的Clicked()槽函数进行绑定。

listWidget.itemClicked.connect(listWidget.itemClicked)

QTabIeWidget

QTableWidget是Qt程序中常用的显示数据表恪的空间,类似于C#中的
DataGrid。QTableWidget是QTableView的子类,它使用标准的数据模型,并且其单元格数据是通过QTableWidgetItem对象来实现的。使用QTableWidget时就需要
QTableWidgetItem,用来表示表格中的一个单元格,整个表格就是用各单元格构建
起来的。

QTableWidget类中的常用方法如表5-6所示。

方法描述
setRowCount(int row)设置QTableWidget表格控件的行数
setColumnCount(int col)设置QTableWidget表格控件的列数
setVerticalHeaderLabels()设置QTableWidget表格控件的水平标签
setVerticalHeaderLabels()设置QTableWidget表格控件的垂直标签
setItem(int,int,QTableWidgetItem)在QTableWidget表格控件的每个选顼的单元空间里添加控件
horizontalHeader()获待QTableWidget表格控件的表格头,以便执行隐藏
rowCount()获得QTableWidget表格控件的行数
columnCount()获得QTableWidget表格控件的列数
setEditTriggers(EditTriggers triggers设置表格是否可编辑。设置编辑规则的枚举值
setSelectionBehavior设置表格的选择行为
setTextAlignment()设置单元格内文字的对齐方式
setSpan(int row,int column,int rowSpanCount,int columnSpanCount)合并单元格,要改变单元格的第row行第column列,要合并rowSpanCount行数和columnSpanCount列数。row:要改变的单元格行数;column:要改变的单元格列数;rowSpanCount:需要合并的行数;columnSpanCount:需要合并的列数
setShowGrid()在默认况下,表格的显示是有网格线的;True:显示网格线;False:不显示网格线
setColumnWidth(intcolumn,int width)设置单元格行的宽度
setRowHeight(int row,int height)设置单元格列的高度

编辑规则的枚举值类型如表5-7所示。

选项描述
QAbstractItemView.NoEditTriggers0No0不能对表格内容行修改
QAbstractItemView.CurrentChanged1Editing1任何时候都能对单元格进行修改
QAbstractItemView.DoubleClicked2Editing2双击单元格
QAbstractItemView.SelectedClicked4Editing4单击己选中的内容
QAbstractItemView.EditKeyPressed8Editing8当修改被按下时修改单元格
QAbstractItemView.EditKEyPressed16Editing16按任意键修改单元格
QAbstractItemView.AllEditTrigger31Editing31包括以上所有条件

表格的选择行为的枚举值类型如表5-8所示。

选项描述
QAbstractItemView.SelectItems0Selecting0选中单个单元格
QAbstractItemView.SelectRowsSelecting1选中一行
QAbstractItemView.SelectColns2Selecting2选中一列

单元恪文本的水平对齐方式如表5-9所示。

选项描述
Qt.AlignLeft与顶部对齐
Qt.AlignRight与底部对齐
Qt.AlignHCenter在可用空间中,居中显示在垂直方向上
Qt.AlignJustify与基线对齐

单元格文本的垂直对齐方式如表5-10所示。

选项描述
Qt.AlignTop与顶部对齐
Qt.ALignBottom与底部对齐
Qt.ALignVCenter在可用空间中,居中显示在垂直方向上
Qt.AlignBaseline与基线对齐

如果要设置水平和垂直对齐方式,比如在表格空间内上下、左右居中对齐,那
么只要使用QLAlignHCenter和Qt.AlignVCenter即可。

基本用法

import sys
from PyQt5.QtWidgets import (QWidget, QTabWidget, QHBoxLayout, QTableWidget, QAbstractItemView, QTableWidgetItem,
                             QApplication)

class Table(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle("QTableWidget 例子")
        self.resize(430, 230)
        conLayout = QHBoxLayout()
        tableWidget = QTableWidget()
        tableWidget.setRowCount(4)
        tableWidget.setColumnCount(3)
        conLayout.addWidget(tableWidget)

        tableWidget.setHorizontalHeaderLabels(['姓名','性别','体重(kg)'])

        newItem=QTableWidgetItem("张三")
        tableWidget.setItem(0,0,newItem)

        newItem=QTableWidgetItem("男")
        tableWidget.setItem(0,1,newItem)

        newItem=QTableWidgetItem("160")
        tableWidget.setItem(0,2,newItem)

        tableWidget.verticalHeader().setVisible(False)

        self.setLayout(conLayout)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    example=Table()
    example.show()
    sys.exit(app.exec_())

运行结果:

image

代码分析:

self.table=QTableWidget(4,3)

上面这行代码构造了一个QTableWidget对象,并且设置表格为4行3列。

tableWidget.setHorizontalHeaderLabels(['姓名','性别','体重(kg)'])

上面这行代码设置了表格头。

 newItem=QTableWidgetItem("张三")

上面这行代码生成了一个QTableWidgetItem对象,名称为"张三"。

上面这行代码将刚才生成的具体单元格加载到表格的第0行第0列处。

在默认情况下,表格里的字符串是可以更改的。

设置表格头

import sys
from PyQt5.QtWidgets import (QWidget, QTabWidget, QHBoxLayout, QApplication, QTableWidget, QHeaderView,
                             QTableWidgetItem)

class Table(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle("QTableWidget demo")
        self.resize(500,300)
        conLayout=QHBoxLayout()
        tableWidget=QTableWidget()
        tableWidget.setRowCount(4)
        tableWidget.setColumnCount(3)
        conLayout.addWidget(tableWidget)

        tableWidget.setHorizontalHeaderLabels(['姓名','性别','体重(kg)'])
        tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

        newItem=QTableWidgetItem("张三")
        tableWidget.setItem(0,0,newItem)

        newItem=QTableWidgetItem("男")
        tableWidget.setItem(0,1,newItem)

        newItem=QTableWidgetItem("160")
        tableWidget.setItem(0,2,newItem)

        self.setLayout(conLayout)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    example=Table()
    example.show()
    sys.exit(app.exec_())

运行截图

image
首先,初始化QTableWidget的实例对象,生成一个4行3列的表格。

tableWidget.setRowCount(4)
        tableWidget.setColumnCount(3)
        conLayout.addWidget(tableWidget)

然后,设置表格的水平表头标签和垂直表头标签。

 tableWidget.setHorizontalHeaderLabels(['姓名','性别','体重(kg)'])
        tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

生成表格,初始化行号和列号后,再设置表格的表头标签,否则是没有效果的。

设置表格头为伸缩模式。

创建一个4行3列的表格,表格头信息“姓名”“性别”“体重(kg)"水平放置,
不设置表格的垂直表头标签,然后使用QTableWidget对象的horizontalHeager()函数
设置表格为自适应的伸缩模式,即可根据窗口大小来改变网格大小。

 tableWidget=QTableWidget()
        tableWidget.setRowCount(4)
        tableWidget.setColumnCount(3)
        conLayout.addWidget(tableWidget)

        tableWidget.setHorizontalHeaderLabels(['姓名','性别','体重(kg)'])
        tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
将表格变为禁止编辑

在默认情况下,表格中的字符串是可以更改的,比如双击一个单元格,就可以修
改原来的内容。如果想禁止这种操作,让表格对用户是只读的,则可以编写如下代码。

tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
设置表格整行选中

表格默认选中的是单个单元格,通过下面的代码可以设置成整行选中。

tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)
将行和列的宽度、高度设置为与所显示内容的宽度、高度相匹配
QTableWidget.resizeColumnToContents()
    QTableWidget.resizeColumnToContents()
表格头的显示与隐藏
tableWidget.verticalHeader().setVisible(False)

对于垂直方向的表头,采用以下代码进行隐藏或显示没置。

tableWidget.horizontalHeader().setVisible(False)
在单元格中放置控件

QTableWidget不仅允许往单元格中放置文字,还允许放置控件,通过
TableWidget.setltem()来添加PyQt的基本控件。

import sys
from PyQt5.QtWidgets import (QWidget,QTableWidget,QHBoxLayout,QApplication,QTableWidgetItem,QAbstractItemView,QComboBox,QPushButton)

class Table(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle("QTableWidget 例子")
        self.resize(430,300)
        conLayout=QHBoxLayout()
        tableWidget=QTableWidget()
        tableWidget.setRowCount(4)
        tableWidget.setColumnCount(3)
        conLayout.addWidget(tableWidget)

        tableWidget.setHorizontalHeaderLabels(['姓名','性别','体重(kg)'])

        newItem=QTableWidgetItem("张三")
        tableWidget.setItem(0,0,newItem)

        comBox=QComboBox()
        comBox.addItem("男")
        comBox.addItem("女")
        comBox.setStyleSheet("QComboBox{margin:3px};")
        tableWidget.setCellWidget(0,1,comBox)

        searchBtn=QPushButton("修改")
        searchBtn.setDown(True)
        searchBtn.setStyleSheet("QPushButton{margin:3px};")

        self.setLayout(conLayout)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    example=Table()
    example.show()
    sys.exit(app.exec_())

运行结果

image

在表格中快速定位到指定行

当tableWidget表格的行数很多时,可以通过输入行号进行直接定位并显示,比
如输入10,就直接显示第10行。

#遍历表格查找对应的具体单元格
item=self.tableWidget.findItem(text,Qt.MatchFixedString)

#获取其行号
row=item[0].row()

#模拟鼠标滚轮快定位到指定行
self.tableWidget.verticalScrollBar().setSliderPosition(row)

import sys
from PyQt5.QtWidgets import *
from PyQt5 import QtCore
from PyQt5.QtGui import QColor,QBrush

class Table(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle("QTableWidget 例子")
        self.resize(600,800)
        conLayout=QHBoxLayout()
        tableWidget=QTableWidget()
        tableWidget.setRowCount(30)
        tableWidget.setColumnCount(4)
        conLayout.addWidget(tableWidget)

        for i in range(30):
            for j in range(4):
                itemContent='(%d,%d)'%(i,j)
                tableWidget.setItem(i,j,QTableWidgetItem(itemContent))
        self.setLayout(conLayout)

        #遍历表查找对应的Item
        text="(10,1)"
        items=tableWidget.findItems(text,QtCore.Qt.MatchExactly)
        item=items[0]
        # 选中单元格
        #item.setSelected(True)
        #设置单元格的背景颜色为红色
        item.setForeground(QBrush(QColor(255,0,0)))

        row=item.row()
        #滚轮定位过去,快速定位到第17行
        tableWidget.verticalScrollBar().setSliderPosition(row)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    example=Table()
    example.show()
    sys.exit(app.exec_())

运行结果

image

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

钢铁男儿

赛博功德充值,BUG退散

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值