• PyQt5高级界面控件


    表格与树

    表格用过QTableWidget,但树没用过
    QTableWidget继承自QTableView,主要区别就是QTableView可以使用自定义的数据模型来显示内容(通过setModel来绑定数据源)
    QTableWidget中的单元格数据是通过QTableWidgetItem对象来实现的。QTableWidget中对表格元素的处理比较优秀,又元素居中,字体如何显示等,修改单元格样式(大概是它是一个一个元素的设置把)
    为什么要用表单,因为表单常常可以用来显示数据库的数据。

    from PyQt5.QtSql import QSqlDatabase  , QSqlQueryModel , QSqlQuery
    

    pyqt5中的QSqlDatabase

    		# 添加数据库类型
    		self.db = QSqlDatabase.addDatabase('QSQLITE')
    		# 设定数据库名称
    		self.db.setDatabaseName('./db/database.db')
    		# 打开数据库
    		self.db.open()
    

    QSqlQueryModel 对sql的查询结果集进行封装

    		# 声明查询模型
    		self.queryModel = QSqlQueryModel(self)
    		# 设置模型到表单列表
    		self.tableView.setModel(self.queryModel)
    		# 设置表格表头
    		self.queryModel.setHeaderData(0,Qt.Horizontal,"编号") 
    		self.queryModel.setHeaderData(1,Qt.Horizontal,"姓名")
    		self.queryModel.setHeaderData(2,Qt.Horizontal,"性别")
    		self.queryModel.setHeaderData(3,Qt.Horizontal,"年龄")
    		self.queryModel.setHeaderData(4,Qt.Horizontal,"院系")
                    # 进行sql查询语句
    self.queryModel.setQuery("select * from student")
    

    QSqlQuery 类似于游标对象

    	# 声明数据库查询对象
    	query = QSqlQuery()
    	# 创建表
    	query.exec("create table student(id int primary key, name vchar, sex vchar, age int, deparment vchar)")
    	
    

    QTableView常常使用setModel来绑定数据源

    		# 设置模型
    		self.tableView.setModel(self.queryModel)
    

    QTableWidget表格中单元格数据是通过QTableWidgetItem对象来实现的。
    这个常用方法很多,但好像都没有与数据库相关联的,也许是由于该数据展现的数据是一个个QTableWidgetItem对象的。

    	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.setEditTriggers(QAbstractItemView.NoEditTriggers)
    		
    		# 设置表格为整行选择
    		#tableWidget.setSelectionBehavior( QAbstractItemView.SelectRows)
    
    		# 将行和列的大小设为与内容相匹配
    		#tableWidget.resizeColumnsToContents()
    		#tableWidget.resizeRowsToContents()
    		
    		#表格表头的显示与隐藏
    		#tableWidget.verticalHeader().setVisible(False)
    		#tableWidget.horizontalHeader().setVisible(False)
    		
    		# 不显示表格单元格的分割线
    		#tableWidget.setShowGrid(False)
            # 不显示垂直表头
    		tableWidget.verticalHeader().setVisible(False)
    		
    		self.setLayout(conLayout)
    ## 填充数据
    		for k in range(15): # 27 examples of DDA  
    			i = k/3  
    			j = k%3  
    			item = QTableWidgetItem()  
    			item.setFlags(Qt.ItemIsEnabled)  #用户点击时表格时,图片被选中  
    			icon = QIcon(r'.\images\bao%d.png' % k  ) 
    			item.setIcon(QIcon(icon )  )  
    									
    			print('e/icons/%d.png i=%d  j=%d' %( k , i , j ) )   				   
    			table.setItem(i,j,item)  
    

    表格的样式

    常见的修饰样式有哪些呢,字体,单元格,表格

    待补
    

    QTreeView

    树形结构QTreeView是通过QTreeWidget和QTreeWidgetItem类实现的,QTreeWidgetItem类实现了节点的添加。

    		self.tree = QTreeWidget()
            # 设置列数
    		self.tree.setColumnCount(2)
            # 设置头的标题
    		self.tree.setHeaderLabels(['Key','Value'])
    		root= QTreeWidgetItem(self.tree)
    # 这里设置两次setText是为了,第一次是为了设置key 第二次是为了设置Value
    		root.setText(0,'root')
    		root.setText(1,'0')
    		
    		child1 = QTreeWidgetItem(root)
    		child1.setText(0,'child1')
    		child1.setText(1,'1')
    		
    		child2 = QTreeWidgetItem(root)
    		child2.setText(0,'child2')
    		child2.setText(1,'2')
    		
    		child3 = QTreeWidgetItem(root)
    		child3.setText(0,'child3')
    		child3.setText(1,'3')		
    		
    		child4 = QTreeWidgetItem(child3)
    		child4.setText(0,'child4')
    		child4.setText(1,'4')
    
    		child5 = QTreeWidgetItem(child3)
    		child5.setText(0,'child5')
    		child5.setText(1,'5')
            
    		self.tree.addTopLevelItem(root)
    		self.tree.clicked.connect( self.onTreeClicked ) # 点击触发相应的子节点
    		# 节点全部展开
    		# self.tree.expandAll()
            		
    		self.setCentralWidget(self.tree) # Widgt中设置居中展示吧
    
    

    常用方法

    容器

    容器肯定有多种容器,没用过

    QStackedWidget
    堆栈窗口控件,在同一时间只有一个控件可以显示
    QTabWidget
    是个控件,控件提供了一个选项卡和一个页面区域,默认显示第一个选项卡的页面。可以通过addTab()将一个控件添加到Tab控件的选项卡中。
    当页面较窄的时候,会自动生成箭头来导航标签的切换。
    QListWidget
    是一个基于条目的接口,用于从列表中添加或删除条目。
    QDockWidget是一个可以停靠在QMainWindow内的窗口控件,它可以保持在浮动状态或者在指定位置作为子窗口附加到主窗口中。
    意思就是类似于隐藏控件了。

    	def __init__(self, parent=None):
    		super(DockDemo, self).__init__(parent)
    		layout = QHBoxLayout()
    		bar=self.menuBar() # 菜单栏工具状态的使用
    		file=bar.addMenu("File") # 菜单名
    		file.addAction("New") # 菜单项
    		file.addAction("save")
    		file.addAction("quit")
    		self.items = QDockWidget("Dockable", self) # 创建可停靠的窗口
    		self.listWidget = QListWidget()
    		self.listWidget.addItem("item1")
    		self.listWidget.addItem("item2")
    		self.listWidget.addItem("item3")
    		self.items.setWidget(self.listWidget)
    		self.items.setFloating(True) # 代表可以悬浮在主控件外
    		self.setCentralWidget(QTextEdit()) # 中间显示文本输入框;这个单独的可以拉伸
    		self.addDockWidget(Qt.RightDockWidgetArea, self.items) # 停靠在窗口的右侧
    		self.setLayout(layout)
    		self.setWindowTitle("Dock 例子")
    
    

    cQFrame

    具体作用未知,常常用在分割QSplitter拆分器中

                    hbox = QHBoxLayout(self)
    		splitter2 = QSplitter(Qt.Vertical) # 拆分器
    		bottom = QFrame() # bottom 
    		bottom.setFrameShape(QFrame.StyledPanel)
    		splitter2.addWidget(bottom )# 添加控件
    #设定最终布局
    		hbox.addWidget(splitter2)
    		self.setLayout(hbox)
    

    不常用

    QMdiArea
    MDI多文档界面;可创建多个独立的窗口
    子窗口都可以放在主窗口容器中,这个容器控件就是QMdiArea
    子窗口在MDI区域进行级联排列布局
    QScrollBar
    提供水平或者垂直的滑动条

    多线程

    多线程中常使用信号与槽

    计时器模块QTimer(定时器)

    周期性的检测主机的CPU值

    Qthread

    事件处理

    网页交互

    信号与槽

    Pyqt5中信号与槽通过object.signal.connect()方法连接,其实在早期的GUI编程中使用的是回调机制,然后QT中采用了这种新机制信号与槽。
    概念:当事件或者状态发生改变时,就会发出信号。同时,信号会触发所有与这个事件(信号)相关的函数(槽)。信号与槽可以是多对多的关系。一个信号可以连接多个槽,一个槽可以连接多个信号。
    过程:发送者(emit发送信号)-->接收者(connect绑定信号与槽函数)-->槽函数
    定义:在Pyqt5中使用pyqtSignal()函数来为QObject创建一个信号,使用pyqtSingnal()函数可以把信号定义为类的属性
    创建信号

    # 参数类型是标准的Python数据类型
    Signal_name = pyqtSignal() # 括号中可加参数
    

    操作信号

    # 绑定槽函数上
    connect()
    # 解绑
    disconnect()
    

    分类:
    1.内置信号与槽(内置信号:btn.clicked,槽:showMsg)

    widget =  QWidget()
    
    def showMsg():
         QMessageBox.information(widget, "信息提示框", "ok,弹出测试信息")
         
    btn = QPushButton( "测试点击按钮", widget) # 这种方式添加到QWidget中
    btn.clicked.connect( showMsg)
    widget.show()
    

    2.自定义信号与槽

    # 信号对象
    class QTypeSignal(QObject):
        # 定义一个信号
        sendmsg = pyqtSignal(object)
        a_msg = pyqtSignal(object)
        def __init__(self):
            super(QTypeSignal, self).__init__()
    
        def run(self):
            # 发射信号
            self.sendmsg.emit('Hello Pyqt5')
            self.a_msg.emit('大啊啊')
    
    
    # 槽对象          
    class QTypeSlot(QObject):
        def __init__(self):
            super(QTypeSlot, self).__init__()
    
            # 槽对象里的槽函数
    
        def get(self, msg):
            print("QSlot get msg => " + msg)
    
    
    if __name__ == '__main__':
        send = QTypeSignal()
        slot = QTypeSlot()
        # 1
        print('--- 把信号绑定到槽函数 ---')
        send.sendmsg.connect(slot.get)
        send.run()
        send.run()
        # 2
        print('--- 把信号断开槽函数 ---')
        send.sendmsg.disconnect(slot.get)
        send.a_msg.connect(slot.get)
        send.run()
    

    1,2组合应用,自定义信号和槽函数(自定义信号:self.button_clicked_signal,自定义槽函数btn_close)

    	button_clicked_signal = pyqtSignal()
    
    	def __init__(self,parent=None):
    		super().__init__(parent)
    		self.setWindowTitle('自定义信号和槽函数示例')
    		self.resize(330,  50 ) 
    		btn = QPushButton('关闭', self)
    		# 连接 信号和槽
    		btn.clicked.connect(self.btn_clicked)
    		# 接收信号,连接到自定义槽函数
    		self.button_clicked_signal.connect(self.btn_close) 
    
    	def btn_clicked(self):
    		# 发送自定义信号,无参数
    		self.button_clicked_signal.emit()
            ## 自定义槽函数 槽函数一般均可自定义的
    	def btn_close(self):
    		self.close()
    

    注意点:信号发出的参数个数一定要大于槽函数接收的参数个数
    解决方法是用

    • 1.lambda表达式
    button1.clicked.connect(lambda: self.onButtonClick(1)) 
    
    • 2.functools中的partial函数
    button1.clicked.connect(partial(self.onButtonClick, 1))   		
    button2.clicked.connect(partial(self.onButtonClick, 2))  
    

    3.装饰器的信号与槽的使用
    就是通过装饰器的方法来定义信号和槽函数

            self.okButton = QPushButton("OK", self)
            #使用setObjectName设置对象名称
            self.okButton.setObjectName("okButton")        
            layout =  QHBoxLayout()
            layout.addWidget(self.okButton)
            self.setLayout(layout)
            # 根据信号名称自动连接到槽函数的核心代码                
            QtCore.QMetaObject.connectSlotsByName(self)
    
    
        # 触发按钮和信号的 装饰器
        @QtCore.pyqtSlot() # 装饰器函数的下方名称是使用setObjectName绑定的才可以触发的。
        def on_okButton_clicked(self):
            print( "点击了OK按钮")
    
  • 相关阅读:
    下载视频
    009 逻辑 + MFC CString
    008 浅拷贝与深拷贝
    007 operator
    006 this指针原理
    005 逻辑 + STL list
    004 list::sort
    003 逻辑 + mfc CList
    001 C++历史和思想
    并查集模板
  • 原文地址:https://www.cnblogs.com/wkhzwmr/p/16353441.html
Copyright © 2020-2023  润新知