Bootstrap

PyQT5 QTableView的简单应用


此文章是笔者在使用pyqt5编写GUI程序碰到问题时候的随笔,方便自己回头复习。欢迎大家留言指正,共同讨论学习。

一.PyQT5简介

PyQt5是基于Digia公司强大的图形程式框架 Qt5 的python接口,由一组python模块构成,同时支持python2和python3, 笔者使用的是python3 版本。PyQt5本身拥有超过620个类和6000函数及方法。在可以运行于多个平台,包括:Unix, Windows, and Mac OS。

二.QTableView介绍

QTableView类用于以表格形式输出信息,可通过自定义的数据模型来显示数据,通过setModel来绑定数据源。

创建一个表格视图
self.table_view = QTableView()

1.表格标题栏(表头)的操作

设置表格标题栏的字体
font = self.table_view.horizontalHeader().font()  # 获取当前表格标题栏的字体
font.setFamily("微软雅黑")  # 修改字体样式
self.table_view.horizontalHeader().setFont(font)  # 重新设置新的字体
设置表格标题是否可见(True: 可见,False:不可见)
self.table_view.verticalHeader().setVisible(False)  # 垂直标题栏不可见
self.table_view.horizontalHeader().setVisible(False) # 水平标题栏不可见
设置表格标题栏是否可被点击
self.table_view.verticalHeader().setSectionsClickable(False) # 垂直标题栏不可被点击
self.table_view.horizontalHeader().setSectionsClickable(False) # 水平标题栏不可被点击
设置表格标题栏的背景色
self.table_view.horizontalHeader().setStyleSheet("QHeaderView::section{background:red;}") # 垂直标题栏背景色为红色
设置表格标题栏的高度
self.table_view.horizontalHeader().setFixedHeight(40)
拖动表格标题栏移动行列
self.table_view.horizontalHeader().setSectionsMovable(True); # 设置可拖动
self.table_view.horizontalHeader().setDragEnabled(True); # 启动拖动
self.table_view.horizontalHeader().setDragDropMode(QAbstractItemView.InternalMove) # 设置拖动模式

2.表格的操作

设置行列填满窗口
self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) # 使表宽度自适应
self.table_view.verticalHeader().setSectionResizeMode(QHeaderView.Stretch) # 使表高度自适应
设置内容与表格相匹配(当设置填满窗口时 就不可以拉伸表头)
self.table_view.resizeColumnsToContents()
self.table_view.resizeRowsToContents()
当一个单元格的内容很长时 通过设置表头来显示完整的单元格内容
self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
设置单元格的选中模式(QAbstractItemView共有五种选中模式)
self.table_view.setSelectionMode(QAbstractItemView.SingleSelection) # 选中一个单元格

五种选中模式如下:

模式说明
QAbstractItemView.NoSelection禁止选择
QAbstractItemView.SingleSelection选中单个目标
QAbstractItemView.MultiSelection选中多个目标
QAbstractItemView.ExtendedSelectionshift键的连续选择
QAbstractItemView.ContiguousSelectionctrl键的不连续的多个选择
禁止编辑(QAbstractItemView有七种编辑模式)
self.table_view.setEditTriggers(QAbstractItemView.NoEditTriggers)

七种编辑模式如下:

模式说明
QAbstractItemView.NoEditTriggers0禁止编辑
QAbstractItemView.CurrentChanged1选择视图中新的数据时触发编辑
QAbstractItemView.DoubleClicked2鼠标双击时触发编辑
QAbstractItemView.SelectedClicked4在一个已经选中的行中单击鼠标时触发编辑
QAbstractItemView.EditKeyPressed8在一个视图选中行中点击鼠标时触发编辑
QAbstractItemView.AnyKeyPressed16在当前选中的数据(单元格)按下任意键触发当前数据项进入编辑状态
QAbstractItemView.AllEditTriggers31以上所有操作行为都触发当前数据项进入编辑状态
设置选中背景色
self.table_view.setStyleSheet("selection-background-color:lightblue;")
设置是否启用滚动条
self.table_view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)  # 启用水平滚动条
self.table_view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)  # 禁用水平滚动条
设置单元格的尺寸
self.table_view.setColumnWidth(0, 100)   # (固定值0,宽度)

3.获取表格数据

self.table_view.currentIndex().row() # 获取所在行数
self.table_view.currentIndex().column()  # 获取所在列数

获得单元格的内容
self.table_view.currentIndex().data()

三. 代码示例

table_view.py

#!/usr/bin/python3
# -*- coding:utf-8 -*-
import sys

from PyQt5.QtCore import Qt
from PyQt5.QtGui import QStandardItemModel, QStandardItem, QCursor, QFont
from PyQt5.QtWidgets import (QWidget, QTableView, QAbstractItemView, QToolTip, qApp, QPushButton,
                             QLabel, QVBoxLayout, QHBoxLayout, QApplication)


class QTableViewPanel(QWidget):
    def __init__(self, users_data):
        super().__init__()

        self.users_data = users_data
        self.users_num = len(users_data)
        self.user_info_num = len(self.users_data[0])

        self.init_ui()
        self.main()

    def init_ui(self):
        """ 界面初始化 """
        self.resize(930, 263)  # 设置窗口 宽 高
        self.setWindowTitle("QTableView界面")  # 设置窗口标题
        self.setFixedSize(self.width(), self.height())

    def set_table_attribute(self):
        """ 设置窗口的一些属性 """
        self.set_table_column_row()
        self.set_table_header()
        self.set_table_init_data()
        self.set_table_v()
        self.set_table_size()
        self.set_table_select()
        self.set_table_select_mode()

        self.set_table_header_visible()
        self.set_table_edit_trigger()
        self.show_table_grid()
        self.set_table_header_font_color()

    def set_table_column_row(self):
        """ 设置表格 行与列"""
        self.model = QStandardItemModel(5, 6)

    def set_table_v(self):
        """ 设置窗口使用的表格视图 """
        self.table_view = QTableView()
        self.table_view.setModel(self.model)

    def set_table_header(self):
        """ 设置表格的表头名称 """
        self.column_name = ['user_id', 'user_name', 'company_address', 'telephone', 'email_address', 'remark']
        self.model.setHorizontalHeaderLabels(self.column_name)

    def set_table_init_data(self):
        """ 给表格输入初始化数据 """
        for i in range(self.users_num):
            for j in range(self.user_info_num):
                user_info = QStandardItem(self.users_data[i][j])
                self.model.setItem(i, j, user_info)
                user_info.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)

    def set_table_size(self):
        """ 设置表格单元格尺寸 """
        self.table_view.setColumnWidth(0, 100)
        self.table_view.setColumnWidth(1, 130)
        self.table_view.setColumnWidth(2, 150)
        self.table_view.setColumnWidth(3, 150)
        self.table_view.setColumnWidth(4, 160)
        self.table_view.setColumnWidth(5, 165)

    def set_table_edit_trigger(self):
        """ 设置表格是否可编辑 """
        self.table_view.setEditTriggers(QAbstractItemView.NoEditTriggers)

    def set_table_select(self):
        """ 设置单元格选中模式 """
        self.table_view.setSelectionBehavior(QAbstractItemView.SelectItems)

    def set_table_select_mode(self):
        """ 单个选中和多个选中的设置 """
        self.table_view.setSelectionMode(QAbstractItemView.SingleSelection)
        self.table_view.doubleClicked.connect(self.get_table_item)
        self.table_view.clicked.connect(self.get_cell_tip)

    def get_cell_tip(self):
        """ 设置单元格提示信息 """
        contents = self.table_view.currentIndex().data()
        QToolTip.showText(QCursor.pos(), contents)

    def set_table_header_visible(self):
        """ 设置表头的显示与隐藏 """
        self.table_view.verticalHeader().setVisible(True)
        self.table_view.horizontalHeader().setVisible(True)

    def get_table_item(self):
        """获取表格中的数据"""
        # row = self.table_view.currentIndex().row() # 获取所在行数
        column = self.table_view.currentIndex().column()  # 获取所在列数
        contents = self.table_view.currentIndex().data()  # 获取数据
        # QToolTip.showText(QCursor.pos(), contents)
        clipboard = qApp.clipboard()  # 获取剪贴板
        clipboard.setText(contents)
        self.copy_tips1.setText("已复制" + self.column_name[column] + ": ")
        self.copy_tips2.setText(contents)
        self.copy_tips2.setStyleSheet("color:red")

    def set_table_header_font_color(self):
        """ 对表头文字的字体、颜色进行设置 """
        self.table_view.horizontalHeader().setFont(QFont("Verdana", 13, QFont.Bold))
        # self.table_view.horizontalHeader().setStyleSheet("") # 设置样式

    def show_table_grid(self):
        """ 设置表格参考线是否可见 """
        self.table_view.setShowGrid(True)

    def set_component(self):
        self.btn_close = QPushButton("关闭")

        self.btn_close.clicked.connect(self.close_window)  # 连接槽函数

        self.label1 = QLabel("当前共:")
        self.label_users_num = QLabel(str(self.users_num))
        self.label3 = QLabel("个用户! 双击单元格可复制单元格中的内容!")
        self.copy_tips1 = QLabel("暂未复制任何内容!")
        self.copy_tips2 = QLabel()

        self.label_users_num.setStyleSheet("color:red")

        self.label1.setFixedWidth(42)
        if len(str(self.users_num)) == 1:
            self.label_users_num.setFixedWidth(12)
        else:
            self.label_users_num.setFixedWidth(22)
        self.btn_close.setFixedSize(80, 32)
        self.copy_tips1.setFixedWidth(170)

    def set_panel_layout(self):
        """ 设置页面布局 """
        v_layout = QVBoxLayout()
        v_layout.addWidget(self.table_view)

        h_layout1 = QHBoxLayout()
        h_layout1.addWidget(self.copy_tips1)
        h_layout1.addWidget(self.copy_tips2)

        h_layout2 = QHBoxLayout()
        h_layout2.addWidget(self.label1)
        h_layout2.addWidget(self.label_users_num)
        h_layout2.addWidget(self.label3)

        h_layout2.addWidget(self.btn_close)

        v_layout.addLayout(h_layout1)
        v_layout.addLayout(h_layout2)
        self.setLayout(v_layout)

    def close_window(self):
        self.close()
        qApp.quit()

    def main(self):
        self.set_table_attribute()
        self.set_component()
        self.set_panel_layout()


if __name__ == '__main__':
    user_data = [
        ["01", "小明", "幸福路1号", "13100000000", '[email protected]', '活泼好动,喜欢唱歌。'],
        ["02", "小红", "点击此处的内容将使用提示显示全部信息", "13100000001", '[email protected]', '乐观开朗,乐于助人。'],
        ["03", "小蓝", "幸福路3号", "13100000002", '[email protected]', '这里也是超出显示的内容:此人较懒,未填简介。'],
        ["04", "小黑", "幸福路4号", "13100000003", '[email protected]', '沉默寡言,爱敲代码。'],
        ["05", "小白", "幸福路5号", "13100000004", '[email protected]', '积极向上,喜欢发呆。']
    ]
    app = QApplication(sys.argv)
    tp = QTableViewPanel(user_data)
    tp.show()
    app.exit(app.exec_())

运行界面如下:
在这里插入图片描述
当单击某个单元格时会使用气泡的样式去显示完整的信息:
在这里插入图片描述
由于设置了垂直滚动条,可拖动滚动条显示余下的内容。笔者这里测试数据只写了5条,所以显示的内容也是5条:
在这里插入图片描述
笔者在代码中设置了双击单元格完成单元格数据的复制操作,复制的文本内容以红色字体表示,双击不同的单元格会替换掉剪贴板中的内容,只会保留最近复制的内容。具体显示如下:
在这里插入图片描述

最后

QTableView是一个控件,与之对应的还有QTableWidget(表格布局),也能实现显示出表格样式的界面效果。笔者这里使用的是手写的测试数据。可以通过后端接口去获取数据库的数据,这里就不做演示了。希望对大家有所帮助,同时也欢迎大家交流探讨,共同学习!

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;