Pyqt5学习笔记七、PYQT5表格控件使用

磊落不羁 by:磊落不羁 分类:pyQt5 时间:3年前 阅读:199 评论:0

七、PYQT5表格控件的使用

PyQt5提供了两种表格控件,分别是TableWidget和TableView,其中,TableView是基于模型的,它是TableWidget的父类,使用TableView时,首先需要建立模型,然后再保存数据;而TableWidget是TableView的升级版本,它已经内置了一个数据存储模型QTableWidgetItem,我们在使用时,不必自己建立模型,而直接使用setItem()方法即可添加数据。所以在实际开发时,推荐使用TableWidget控件作为表格。

image-20221223114816676

QTableWidgetItem类表示QTableWidget中的单元格,一个表格就是由多个单元格组成的,QTableWidgetItem类的常用方法如表

image-20221223114843965

1、在表格中显示数据库数据

使用TableWidget控件显示数据主要用到QTableWidgetItem类,使用该类创建表格中的单元格,并指定要显示的文本或者图标后,即可使用TableWidget对象的setItem()方法将其添加到表格中。

import sys

from PyQt5.QtWidgets import *
import pymysql
class demo(QTabWidget):
    def __init__(self):
        super(demo, self).__init__()
        self.setupUi()
    def setupUi(self):
        self.setWindowTitle("使用表格显示数据库中数据")
        self.resize(1240,380)
        vhayout=QHBoxLayout()   #S水平布局
        #连接数据库
        conn=pymysql.connect("localhost","ziyuan","841109","ziyuan")
        cursor=conn.cursor()
        sql="select * from `ziyuan`;"
        cursor.execute(sql)
        res=cursor.fetchall()
        row=cursor.rowcount    #在游标中获取行数
        vol=len(res[0])    #通过第一个结果数量确定列数
        cursor.close()
        conn.close()
        # 创建表格 并开始设置
        table = QTableWidget()  #创建
        table.setRowCount(row)   #设置行数
        table.setColumnCount(vol)  #设置列数
        table.setHorizontalHeaderLabels(['id','单元','分类','标题','类型','描述','路径','作者'])
        #循环写入数据 使用setitem
        for i in range(row):
            for j in range(vol):
                data=QTableWidgetItem(str(res[i][j]))
                table.setItem(i,j,data)

        #这几项设置设置在数据写入之前无效。以后要都要写在数据写入之后
        table.resizeColumnsToContents() #列宽跟随内容变化
        table.resizeRowsToContents() #行高跟随内容变化而变化
        table.setAlternatingRowColors(True)  #表格颜色交错显示

        vhayout.addWidget(table) #使表格添加到水平布局中
        self.setLayout(vhayout)

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

image-20221224094419081

2、隐藏标题

表格在显示数据时,默认会以编号的形式自动形成一列垂直标题,如果需要隐藏,可以使用verticalHeader()获取垂直标题,然后使用setVisible()方法将其隐藏。

   table.verticalHeader().setVisible(False) # 隐藏垂直标题

增加在数据之后

image-20221224094736712

table.horizontalHeader().setVisible(False)  #隐藏水平标题  也是添加在数据之后较为安全

image-20221224094953279

3、设置最后一列自动填充容器

表格中的列默认会以默认宽度显示,但如果遇到窗口伸缩的情况,在放大窗口时,由于表格是固定的,就会造成窗口中可能会出现大面积的空白区域,影响整体的美观。在PyQt5中可以使用setstret-chlastSection( )方法将表格的最后一列设置为自动伸缩列,这样就可以自动填充整个容器。

table.horizontalHeader().setStretchLastSection(True)   # 设置最后一列自动填充容器
#上面的代码将最后一列设置为了自动伸缩列,除此之外,还可以将整个表格设置为自动伸缩模式,这样,在放大或者缩小窗口时,整个表格的所有列都会按比例自动缩放。代码如下:      
table.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)

最后一列自动伸缩

image-20221224095307158

所有表格按比例自动伸缩。综合看 最后一列自动伸缩实用性更强。

image-20221224095621334

4、禁止编辑单元格

当双击表格中的某个单元格时,表格中的数据在默认情况下是可以编辑的,但如果只需要查看数据,则可以使用表格对象的setEditTriggers()方法将表格的单元格设置为禁止编辑状态。

table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)    # 禁止编辑单元格

image-20221224095943043

5、设置单元格的文本颜色

使用QTableWidgetItem对象的setForeground()方法可以设置单元格内文本的颜色,其参数为一个QBrush对象,在该对象中可以使用颜色名或者RGB值来对颜色进行设置。

data.setForeground(QtGui.QBrush(QtGui.QColor("green")))   # 设置单元格文本颜色

image-20221224100249864

运行效果如下:

image-20221224100337910

如果需要设置单元格的背景颜色,可以使用setBackground()方法,例如,将单元格背景设置为黄色,代码如下:

data.setBackground(QtGui.QBrush(QtGui.QColor("yellow")))    # 设置单元格背景颜色

image-20221224100512209

运行效果如下

image-20221224100455965

6、设置指定列的排序方式

使用QTableWidget对象的sortItems()方法,可以设置表格中指定列的排序方式。代码同样放在数据之后

sortItems(column, order)
#column:一个整数数字,表示要进行排序的列索引。  
#order:一个枚举值,指定排序方式,其中,Qt.DescendingOrder表示降序,Qt.AscendingOrder表示升序。

image-20221224100912537

7、在指定列中显示图片

表格除了可以显示文字,还可以显示图片,显示图片可以在创建QTableWidgetItem对象时传入QIcon图标对象实现。

for j in range(vol):
    if j==4:
        data=QTableWidgetItem(QtGui.QIcon('haokan.ico'),str(res[i][j]))  #这里在第四列加入图片
    else:
        data=QTableWidgetItem(str(res[i][j]))

image-20221224101407098

8、向指定列中添加PyQt5标准控件

TableWidget表格不仅可以显示文字、图片,还可以显示PyQt5的标准控件,实现该功能需要使用setCellWidget()方法。

 setCellWidget(row, column, QWidget)
#row:一个整数数字,表示要添加控件的单元格的行索引。  
#column:一个整数数字,表示要添加控件的单元格的列索引。  
#QWidget:PyQt5标准控件

image-20221224102122669

image-20221224102152659

9、合并单元格

在实际项目开发中,经常遇到合并单元格的情况。在PyQt5中合并表格的单元格,需要使用setSpan()方法。

setSpan(row, column, rowSpanCount,columnSpanCount)
#row:一个整数数字,表示要改变的单元格的行索引。  
#column:一个整数数字,表示要改变的单元格的列索引。  
#rowSpanCount:一个整数数字,表示需要合并的行数。
#columnSpanCount:一个整数数字,表示需要合并的列数。

比方把第八列合并

image-20221224102758686

运行效果

image-20221224102739577

10、获取单元格信息

pyqt中的QTableWigget获取点击单元格的内容,行,列。获取这些信息后可以对数据进行更高级别的操作。比如增删改查。

image-20221224105027039

#信号
    table.itemClicked.connect(self.showdata) 

def showdata(self,item=None):
    if item is None:
        return
    else:
        row=item.row()
        col=item.column()
        text=item.text()
    QMessageBox.information(self,"数据",f"行:{row};列;{col}内容{text}")

11、单元格右键菜单

信号:

self.table.setContextMenuPolicy(Qt.CustomContextMenu)  # 右键菜单,如果不设为CustomContextMenu,无法使用customContextMenuRequested
self.table.customContextMenuRequested.connect(self.showContextMenu)

右键菜单函数:

def showContextMenu(self):  # 创建右键菜单
    self.table.contextMenu = QMenu(self)
    self.actionA = self.table.contextMenu.addAction(u'动作a')
    # self.actionA = self.view.contextMenu.exec_(self.mapToGlobal(pos))  # 1
    self.table.contextMenu.popup(QCursor.pos())  # 2菜单显示的位置
    self.actionA.triggered.connect(self.actionHandler)  #菜单点击发射信号
    # self.view.contextMenu.move(self.pos())  # 3
    self.table.contextMenu.show() #显示菜单

def actionHandler(self):
    print('yes')  #菜单 动作a执行的动作函数

image-20221224112131182

12、删除数据

self.table.removeRow(4) #移除第5行
self.table.removeColumn(7) #移除第8列
self.table.removeCellWidget(1,2)  #移除第二行第三列的控件

image-20221224113242970

运行效果:

image-20221224113302879

如果要移除数据库中数据,还要配合数据库cursor.excute(SQL) SQL为删除语句

删除所有数据

self.tableWidget.setRowCount(0) #设置0行
self.tableWidget.clearContents() #清空所有内容

13、信号

QTableWidget非继承自父类的信号如下

cellActivated(int row, int column):对应项获得了焦点时发射本信号

cellChanged(int row, int column):对应项的各种角色数据发生了变化时发射本信号

cellClicked(int row, int column):对应项鼠标点击时发射本信号

cellDoubleClicked(int row, int column):对应项鼠标双击时发射本信号

cellEntered(int row, int column):鼠标光标进入到对应项范围内时发射本信号

cellPressed(int row, int column):鼠标在对应项范围内按下时发射本信号

currentCellChanged(int currentRow, int currentColumn, int previousRow, int previousColumn):当前项发生切换时触发

currentItemChanged(QTableWidgetItem current, QTableWidgetItem previous):当前项发生切换时触发

itemActivated(QTableWidgetItem item):项获得了焦点时触发

itemChanged(QTableWidgetItem item):对应项的各种角色数据发生了变化时发射本信号

itemClicked(QTableWidgetItem item):对应项鼠标点击时发射本信号

itemDoubleClicked(QTableWidgetItem item):对应项鼠标双击时发射本信号

itemEntered(QTableWidgetItem item):鼠标光标进入到对应项范围内时发射本信号

itemPressed(QTableWidgetItem item):鼠标在对应项范围内按下时发射本信号

itemSelectionChanged():当选中的项发生变化时发射本信号,选中的项通过selectedItems() 方法获取

以上信号很多都是同样的条件触发,只是信号签名不同,具体看应用需要的数据来确认选择哪个信号来处理。

本章节案例完整代码

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

from PyQt5.QtWidgets import *
import pymysql
class demo(QTabWidget):
    def __init__(self):
        super(demo, self).__init__()
        self.setupUi()
    def setupUi(self):
        self.setWindowTitle("使用表格显示数据库中数据")
        self.resize(1240,380)
        vhayout=QHBoxLayout()   #S水平布局
        #连接数据库
        conn=pymysql.connect("localhost","ziyuan","841109","ziyuan")
        cursor=conn.cursor()
        sql="select * from `ziyuan`;"
        cursor.execute(sql)
        res=cursor.fetchall()
        row=cursor.rowcount    #在游标中获取行数
        vol=len(res[0])    #通过第一个结果数量确定列数
        cursor.close()
        conn.close()
        # 创建表格 并开始设置
        self.table = QTableWidget()  #创建
        self.table.setRowCount(row)   #设置行数
        self.table.setColumnCount(vol)  #设置列数
        self.table.setHorizontalHeaderLabels(['id','单元','分类','标题','类型','描述','路径','作者'])
        #循环写入数据 使用setitem
        for i in range(row):
            for j in range(vol):
                if j==4:
                    data=QTableWidgetItem(QtGui.QIcon('haokan.ico'),str(res[i][j]))
                elif j==2:
                    comobox=QComboBox() #定义一个选择框
                    comobox.addItems(['1','2','3','4','5','6'])
                    comobox.setCurrentIndex(res[i][j]-1) #默认选择数据库数字,因为索引从0开始 所以减1
                    self.table.setCellWidget(i,2,comobox)  #设置控件
                else:
                    data=QTableWidgetItem(str(res[i][j]))

                data.setForeground(QtGui.QBrush(QtGui.QColor("green")))
                data.setBackground(QtGui.QBrush(QtGui.QColor("yellow")))
                self.table.setItem(i,j,data)

         # 这几项设置设置在数据写入之前无效。以后要都要写在数据写入之后x
        self.table.sortItems(4,QtCore.Qt.DescendingOrder) #设置第五列降序
        self.table.setSpan(0,8,row,1)  #将第八列合并
        self.table.setSpan(0,9,row,1)  #将第九列合并
        self.table.resizeColumnsToContents() #列宽跟随内容变化
        self.table.resizeRowsToContents() #行高跟随内容变化而变化
        self.table.setAlternatingRowColors(True)  #表格颜色交错显示
        self.table.verticalHeader().setVisible(False)  #隐藏垂直标题
        self.table.horizontalHeader().setVisible(False)  #隐藏水平标题
        self.table.horizontalHeader().setStretchLastSection(True) #设置最后一列自动伸缩
        # table.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch) #所有项目 按比例自动伸缩
        self.table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers) #禁止编辑单元格

        vhayout.addWidget(self.table) #使表格添加到水平布局中
        self.setLayout(vhayout)
        #信号
        self.table.itemClicked.connect(self.showdata)
        self.table.setContextMenuPolicy(Qt.CustomContextMenu)  # 右键菜单,如果不设为CustomContextMenu,无法使用customContextMenuRequested
        self.table.customContextMenuRequested.connect(self.showContextMenu)
        self.table.removeRow(4)
        self.table.removeColumn(7)
        self.table.removeCellWidget(1,2)
        self.table.cell

    def showdata(self,item=None):
        if item is None:
            return
        else:
            row=item.row()
            col=item.column()
            text=item.text()
        QMessageBox.information(self,"数据",f"行:{row};列;{col}内容{text}")

    def showContextMenu(self):  # 创建右键菜单
        self.table.contextMenu = QMenu(self)
        self.actionA = self.table.contextMenu.addAction(u'动作a')
        # self.actionA = self.view.contextMenu.exec_(self.mapToGlobal(pos))  # 1
        self.table.contextMenu.popup(QCursor.pos())  # 2菜单显示的位置
        self.actionA.triggered.connect(self.actionHandler)
        # self.view.contextMenu.move(self.pos())  # 3
        self.table.contextMenu.show()

    def actionHandler(self):
        print('yes')


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

其他未尽知识点其他文章在补充。

非特殊说明,本文版权归原作者所有,转载请注明出处

本文地址:http://php.liulei.com.cn/?type=acticle&id=72

评论列表

发表评论

  • 昵称(必填)
  • 邮箱
  • 网址

TOP