PyQt5入门复杂控件 视图 & MVC设计模式 & 表格

更新时间:2021-02-03 16:45:42点击次数:343次
一.显示二维表数据
显示二维表数据(QTableVi ew控件)
数据源 Model
需要创建QTableView实例和一个数据源(Model) ,然后将两者关联,这个体系类似于MVC模式。
一个QTableView实例可以存放不同的数据源,一个数据源也可以对应不同的QTableView实例。
MVC: Model  Viewer  Controller 即将数据Model和前端视图Viewer分离,通过控制器Controller 来控制。
MVC的目的是将后端的数据和前端页面的耦合度降低。
代码:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import * 
class TableView(QWidget):
    def __init__(self):
        super(TableView, self).__init__()
        self.setWindowTitle('QTableView表格视图控件演示')
        self.resize(500,300)
        self.model=QStandardItemModel(4,3)#二维表4行3列
        #数据表的字段
        self.model.setHorizontalHeaderLabels(['id','name','age'])
        self.tableView=QTableView()
        #关联QTableView控件和Model
        self.tableView.setModel(self.model)
        #添加数据
        item11=QStandardItem('1') #一个QStandardItem就是一个单元格
        item12 = QStandardItem('Kobe')
        item13 = QStandardItem('24')
        self.model.setItem(0,0,item11)
        self.model.setItem(0, 1, item12)
        self.model.setItem(0, 2, item13)
        #可跳行添加数据
        item31 = QStandardItem('7')
        item32 = QStandardItem('Durant')
        item33 = QStandardItem('35')
        self.model.setItem(2, 0, item31)
        self.model.setItem(2, 1, item32)
        self.model.setItem(2, 2, item33) 
        #垂直布局
        layout=QVBoxLayout()
        layout.addWidget(self.tableView)
        self.setLayout(layout)
if __name__=='__main__':
    app=QApplication(sys.argv)
    main=TableView()
    main.show()
    sys.exit(app.exec_()) 
运行结果:
二.显示列数据
代码:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QStringListModel  
class ListView(QWidget):
    def __init__(self):
        super(ListView, self).__init__()
        self.setWindowTitle('ListView例子')
        self.resize(300,270)
        layout=QVBoxLayout() 
        listView=QListView()
        #数据源
        listModel=QStringListModel()
        self.list=['列表项1','列表项2','列表项3']
        listModel.setStringList(self.list)      
        #关联视图与数据源
        listView.setModel(listModel)       
        listView.clicked.connect(self.clicked)
        layout.addWidget(listView)
        self.setLayout(layout)
    def clicked(self,item):
        QMessageBox.information(self,'QListView','您选择了:'+self.list[item.row()]) 
if __name__=='__main__':
    app=QApplication(sys.argv)
    main=ListView()
    main.show()
    sys.exit(app.exec_()) 
运行结果:
三.扩展的列表控件
代码:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QStringListModel
'''
QListWidget是QListView的子类
添加了很多API,支持MVC模式,也支持非MVC模式,即数据直接添加到控件上
''' 
class ListWidget(QMainWindow):
    def __init__(self):
        super(ListWidget, self).__init__()
        self.setWindowTitle('ListWidget例子')
        self.resize(300,270)
        #直接添加的方式适合少量的数据的时候
        self.listWidget=QListWidget()
        #self.listWidget.resize(300,120)
        self.listWidget.addItem('item1')
        self.listWidget.addItem('item2')
        self.listWidget.addItem('item3')
        self.listWidget.addItem('item4')
        self.listWidget.addItem('item5')
        self.listWidget.itemClicked.connect(self.clicked)
        #设置中心控件之后,会铺满整个屏幕,无需再单独设置listWidget尺寸
        self.setCentralWidget(self.listWidget) 
    def clicked(self,index):
        QMessageBox.information(self,'ListWidget','您选择了:'+self.listWidget.item(self.listWidget.row(index)).text())
if __name__=='__main__':
    app=QApplication(sys.argv)
    main=ListWidget()
    main.show()
    sys.exit(app.exec_())
运行结果:
四.扩展的表格控件
每一个Cell (单元格) 是一个QTableWidgetItem
代码:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import * 
'''
QTableWidget是QTableView的子类
添加了很多API,支持MVC模式,也支持非MVC模式,即数据直接添加到控件上
'''
class TableWidget(QWidget):
    def __init__(self):
        super(TableWidget, self).__init__()
        self.initUI()
    def initUI(self):
        self.setWindowTitle('QTableWidget演示')
        self.resize(430, 230) 
        layout = QHBoxLayout()
        tablewidget = QTableWidget()
        # 4行3列
        tablewidget.setRowCount(4)
        tablewidget.setColumnCount(3)
        tablewidget.setHorizontalHeaderLabels(['name','age','address'])
        nameItem=QTableWidgetItem('小明')
        tablewidget.setItem(0,0,nameItem)
        ageItem = QTableWidgetItem('24')
        tablewidget.setItem(0, 1, ageItem)
        addressItem = QTableWidgetItem('北京')
        tablewidget.setItem(0, 2, addressItem)
        #禁止编辑
        tablewidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
        #整行选择
        tablewidget.setSelectionBehavior(QAbstractItemView.SelectRows)
        #调整列和行
        tablewidget.resizeColumnsToContents()
        tablewidget.resizeRowsToContents()
        #隐藏表格头
        tablewidget.horizontalHeader().setVisible(False) #隐藏水平方向的表格头
        #tablewidget.verticalHeader().setVisible(False) #隐藏垂直方向的表格头
        #设置表格头内容
        tablewidget.setVerticalHeaderLabels(['a','b']) #垂直方向表格头前两个设为a,b
        #隐藏表格线
        tablewidget.setShowGrid(False)
        layout.addWidget(tablewidget)
        self.setLayout(layout) 
if __name__=='__main__':
    app=QApplication(sys.argv)
    main=TableWidget()
    main.show()
    sys.exit(app.exec_()) 
运行结果:
五.在单元格中放置控件
在单元格中放置控件
setItem:将文本放到单元格中
setCellWidget:将控件放到单元格中
setStyleSheet设置控件的样式(QSS)
代码:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import * 
'''
QTableWidget是QTableView的子类
添加了很多API,支持MVC模式,也支持非MVC模式,即数据直接添加到控件上
'''
class TableWidget(QWidget):
    def __init__(self):
        super(TableWidget, self).__init__()
        self.initUI()
    def initUI(self):
        self.setWindowTitle('在单元格中放置控件')
        self.resize(430, 300)
        layout = QHBoxLayout()
        tableWidget = QTableWidget()
        # 4行3列
        tableWidget.setRowCount(4)
        tableWidget.setColumnCount(3)
        tableWidget.setHorizontalHeaderLabels(['name','age','weigh(kg)'])
        textItem=QTableWidgetItem('小明')
        #setItem:将文本放到单元格中
        tableWidget.setItem(0,0,textItem)
        #下拉框
        combox=QComboBox()
        combox.addItem('男')
        combox.addItem('女')
        #setStyleSheet设置控件的样式(QSS)(类似于web中的CSS),即Qt StyleSheet(n.样式表)
        combox.setStyleSheet('QComboBox{margin:3px};')#设置控键距离上下左右的单元格的距离(距离)
        #setCellWidget:将控件放到单元格中
        tableWidget.setCellWidget(0,1,combox)
        modifyButton=QPushButton('修改')
        #默认是按下的状态
        modifyButton.setDown(True)
        modifyButton.setStyleSheet('QPushButton{margin:3px};')
        tableWidget.setCellWidget(0,2,modifyButton) 
        layout.addWidget(tableWidget)
        self.setLayout(layout)
if __name__=='__main__':
    app=QApplication(sys.argv)
    main=TableWidget()
    main.show()
    sys.exit(app.exec_()) 
运行结果:
六.在表格中搜索Cell和行定位
在表格中快速定位到特定的行
1.数据的定位: findItems ,返回一个列表
2.如果找到了满足条件的单元格,会定位到单元格所在的行: setSliderPosition(row)
代码:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import * 
class DataLocation(QWidget):
    def __init__(self):
        super(DataLocation, self).__init__()
        self.initUI()
    def initUI(self):
        self.setWindowTitle('在表格中搜索Cell和行定位')
        self.resize(600, 800) 
        layout = QHBoxLayout()
        tableWidget=QTableWidget()
        tableWidget.setRowCount(40)
        tableWidget.setColumnCount(4)
        for i in range(40):
            for j in range(4):
                itemContent='(%d,%d)'%(i,j)
                tableWidget.setItem(i,j,QTableWidgetItem(itemContent))
        self.setLayout(layout)
        #搜索满足条件的Cell
        text='(13,1)'
        text1='(1,'
        #参数一:要匹配的文本 ; 参数二:搜索模式,返回一个列表
        #items=tableWidget.findItems(text,Qt.MatchExactly)#搜索模式设为精确匹配,必须一模一样才行
        items = tableWidget.findItems(text1, Qt.MatchStartsWith)#搜索模式为匹配以...为开头的字符串,这里看text1,即以(1,开头的的字符串
        length=len(items)
        if length>0:
            print('匹配项个数:',len(items))
            for i in range(length):
                item = items[i]
                # 背景色
                item.setBackground(QBrush(QColor(0, 255, 0)))  # rgb
                # 前景色,即文字的颜色
                item.setForeground(QBrush(QColor(255, 0, 0)))
                # 当前项所在的行
                row = item.row()
                # 定位到指定的行
                tableWidget.verticalScrollBar().setSliderPosition(row)
        layout.addWidget(tableWidget)
        self.setLayout(layout) 
if __name__=='__main__':
    app=QApplication(sys.argv)
    main=DataLocation()
    main.show()
    sys.exit(app.exec_()) 
运行结果:
七.设置单元格字体和颜色
代码:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import * 
class CellFontAndColor(QWidget):
    def __init__(self):
        super(CellFontAndColor, self).__init__()
        self.initUI() 
    def initUI(self):
        self.setWindowTitle('设置单元格字体和颜色')
        self.resize(430, 230)
        layout = QHBoxLayout()
        tableWidget=QTableWidget()
        tableWidget.setRowCount(4)
        tableWidget.setColumnCount(3)
        tableWidget.setHorizontalHeaderLabels(['name','sex','weigh(kg)']) 
        newItem=QTableWidgetItem('小明')#单元格的数据项
        newItem.setFont(QFont('Times',14,QFont.Black))#字体,字号,颜色
        newItem.setForeground(QBrush(QColor(255,0,0)))
        tableWidget.setItem(0,0,newItem) 
        newItem = QTableWidgetItem('女')
        newItem.setForeground(QBrush(QColor(255, 255, 0)))
        newItem.setBackground(QBrush(QColor(0,0,255)))#rgb
        tableWidget.setItem(0, 1, newItem) 
        newItem = QTableWidgetItem('100')
        newItem.setFont(QFont('Times', 20, QFont.Black))
        newItem.setForeground(QBrush(QColor(0, 0, 255)))
        tableWidget.setItem(0, 2, newItem) 
        layout.addWidget(tableWidget)
        self.setLayout(layout) 
if __name__=='__main__':
    app=QApplication(sys.argv)
    main=CellFontAndColor()
    main.show()
    sys.exit(app.exec_()) 
运行结果:
八.按表格的某一列排序
按列排序
1.按哪一列排序
2.排序类型:升序或降序
sortItems( columnIndex,orderType)
代码:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import * 
class CellFontAndColor(QWidget):
    def __init__(self):
        super(CellFontAndColor, self).__init__()
        self.initUI() 
    def initUI(self):
        self.setWindowTitle('设置单元格字体和颜色')
        self.resize(540, 230)
        layout = QHBoxLayout()
        self.tableWidget=QTableWidget()#表格对象
        self.tableWidget.setRowCount(4)
        self.tableWidget.setColumnCount(3)
        self.tableWidget.setHorizontalHeaderLabels(['name','sex','weigh(kg)']) 
        #添加数据
        newItem=QTableWidgetItem('张三')
        self.tableWidget.setItem(0,0,newItem)
        newItem = QTableWidgetItem('男')
        self.tableWidget.setItem(0, 1, newItem)
        newItem = QTableWidgetItem('165')
        self.tableWidget.setItem(0, 2, newItem) 
        newItem = QTableWidgetItem('李四')
        self.tableWidget.setItem(1, 0, newItem)
        newItem = QTableWidgetItem('女')
        self.tableWidget.setItem(1, 1, newItem)
        newItem = QTableWidgetItem('120')
        self.tableWidget.setItem(1, 2, newItem) 
        newItem = QTableWidgetItem('王五')
        self.tableWidget.setItem(2, 0, newItem)
        newItem = QTableWidgetItem('男')
        self.tableWidget.setItem(2, 1, newItem)
        newItem = QTableWidgetItem('130')
        self.tableWidget.setItem(2, 2, newItem)
        #点击按钮排序
        self.btn=QPushButton('升序')
        self.btn.clicked.connect(self.order)
        #常量
        self.orderType=Qt.DescendingOrder
        layout.addWidget(self.tableWidget)
        layout.addWidget(self.btn)
        self.setLayout(layout) 
    #升降序来回切换
    def order(self):
        if self.orderType == Qt.DescendingOrder:
            self.orderType=Qt.AscendingOrder
            self.btn.setText('降序')#重命名按钮名,setText设置按钮显示文本
        else:
            self.orderType = Qt.DescendingOrder
            self.btn.setText('升序')
        #print(Qt.DescendingOrder)
        #print(self.orderType)
        self.tableWidget.sortItems(2,self.orderType)#按照第三列的数据项排序
        #self.tableWidget.sortItems(2, Qt.DescendingOrder)
if __name__=='__main__':
    app=QApplication(sys.argv)
    main=CellFontAndColor()
    main.show()
    sys.exit(app.exec_())

运行结果:
点击排序每次是升序和降序依次切换。
(初始状态)  (升序后) (降序后)

本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是一个个人学习交流的平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽,造成漏登,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

  • 项目经理 点击这里给我发消息
  • 项目经理 点击这里给我发消息
  • 项目经理 点击这里给我发消息
  • 项目经理 点击这里给我发消息