06.PyQt5高级界面控------PyQt5编程开发

时间:2022-08-05 23:05:06

一、表格与树

    表格与树解决的问题是如何在一个控件中有规律地呈现更多的数据。解决该问题的两种控件类为表格结构的控件类,树形结构的控件类。

1、QTableView

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

    QStringListModel:存储一组字符串

    QStandardItemModel:存储任意层次结构的数据

    QDirModel:对文件系统进行封装

    QSqlQueryModel:对SQL的查询结构集进行封装

    QSqlTableModel:对SQL中的表格进行封装

    QSqlRelationalTableModel:对带有foreign key的SQL表格进行封装

    QSortFilterProxyModel:对模型中的数据进行排序或过滤

    QTableView的使用例子:

# -*- coding: utf-8 -*-
  '''
  【简介】
  PyQT5中QTableView表格视图控件的例子
 
 
  '''
   
  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(['标题1','标题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_())

运行结果:

    06.PyQt5高级界面控------PyQt5编程开发

2、QListView

    常用方法:setModel():用来设置View所关联的Model,可以使用Python原生的list作为数据源Model

                    selectedItem():选中Model中的条目

                    isSelected():判断Model中的某条条目是否被选中

    常用信号:clicked:当单击某项时,信号被发射

                    doubleClicked:当双击某项时,信号被发射

使用QListView控件例子如下:

# -*- coding: utf-8 -*-
   
  '''
  【简介】
  PyQt5中 QListView 例子
 
  '''
   
  from PyQt5.QtWidgets import QApplication, QWidget , QVBoxLayout , QListView, QMessageBox
  from PyQt5.QtCore import QStringListModel
  import sys
   
  class ListViewDemo(QWidget):
  def __init__(self, parent=None):
  super(ListViewDemo, self).__init__(parent)
  self.setWindowTitle("QListView 例子")
  self.resize(300, 270)
  layout = QVBoxLayout()
   
  listView = QListView()
  slm = QStringListModel();
  self.qList = ['Item 1','Item 2','Item 3','Item 4' ]
  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_())

运行结果:

06.PyQt5高级界面控------PyQt5编程开发

3、QListWidget

    它是一个基于条目的接口,用于从列表中添加或删除条目。列表中的每个条目都是一个QListWidgetItem对象。QListWidget可以设置为多重选择。

    QListWidget类中的常用方法为:

    addItem():在列表中添加QListWidgetItem对象或字符串

    addItems():添加列表中的每个条目

    insertItem():在指定的索引处插入条目

    clear():删除列表的内容

    setCurrentItem():设置当前所选条目

    sortItems():按升序重新排列条目

常用信号为:currentItemChanged:当列表中的条目发生改变时发射此信号

                    itemClicked:当点击列表中的条目时发射此信号

QListWidget使用例子:

# -*- coding: utf-8 -*-
   
  '''
  【简介】
  PyQt5中 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("Item 1");
  listWidget.addItem("Item 2");
  listWidget.addItem("Item 3");
  listWidget.addItem("Item 4");
  listWidget.setWindowTitle('QListwidget 例子')
  listWidget.itemClicked.connect(listWidget.clicked)
  listWidget.show()
  sys.exit(app.exec_())

运行结果:

06.PyQt5高级界面控------PyQt5编程开发

4、QTableWidget

    它是Qt程序中常用的显示数据表格的控件。

06.PyQt5高级界面控------PyQt5编程开发

06.PyQt5高级界面控------PyQt5编程开发

QTableWidget基本用法例子:

    

# -*- coding: utf-8 -*-
   
  '''
  【简介】
  PyQT5中单元格的基本例子
 
  '''
   
  import sys
  from PyQt5.QtWidgets import (QWidget, QTableWidget, QHBoxLayout, QApplication, QTableWidgetItem, QAbstractItemView )
   
  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.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)
   
  if __name__ == '__main__':
  app = QApplication(sys.argv)
  example = Table()
  example.show()
  sys.exit(app.exec_())

运行结果:

06.PyQt5高级界面控------PyQt5编程开发

5、QTreeView

    它实现了树形结构,其中QTreeWidget常用方法为:

    setColumnWidth(int column,int width):将指定列的宽度设置为给定的值

    insertTopLevelItems():在视图的顶层索引中插入项目列表

    expandAll():展开所有的树形节点

    invisibleRootItem():返回树形控件中不可见的根选项(Root Item)

    selectedItems():返回所有选定的非隐藏项目的列表

    QTreeWidgetItem类中的常用方法为:

    addChild():将子项追加到子列表中

    setText():设置显示的节点文本

    Text():返回显示的节点文本

    setCheckState(column,state):设置指定列的选中状态

    setIcon(column,icon):在指定的列中显示图标

树形结构实现的例子:

    

'''
  【简介】
  PyQT5中 QTreeWidget 例子
 
 
  '''
   
  import sys
  from PyQt5.QtWidgets import *
  from PyQt5.QtGui import QIcon , QBrush , QColor
  from PyQt5.QtCore import Qt
   
  class TreeWidgetDemo(QMainWindow):
  def __init__(self,parent=None):
  super(TreeWidgetDemo,self).__init__(parent)
  self.setWindowTitle('TreeWidget 例子')
  self.tree = QTreeWidget()
  # 设置列数
  self.tree.setColumnCount(2)
  # 设置头的标题
  self.tree.setHeaderLabels(['Key','Value'])
  # 设置根节点
  root= QTreeWidgetItem(self.tree)
  root.setText(0,'root')
  root.setIcon(0,QIcon("./images/root.png"))
  # 设置列宽
  self.tree.setColumnWidth(0, 160)
   
  ### 设置节点的背景颜色
  #brush_red = QBrush(Qt.red)
  #root.setBackground(0, brush_red)
  #brush_green = QBrush(Qt.green)
  #root.setBackground(1, brush_green)
   
  # 设置子节点1
  child1 = QTreeWidgetItem(root)
  child1.setText(0,'child1')
  child1.setText(1,'ios')
  child1.setIcon(0,QIcon("./images/IOS.png"))
  child1.setCheckState(0, Qt.Checked)
   
  # 设置子节点2
  child2 = QTreeWidgetItem(root)
  child2.setText(0,'child2')
  child2.setText(1,'')
  child2.setIcon(0,QIcon("./images/android.png"))
   
  # 设置子节点3
  child3 = QTreeWidgetItem(child2)
  child3.setText(0,'child3')
  child3.setText(1,'android')
  child3.setIcon(0,QIcon("./images/music.png"))
   
  self.tree.addTopLevelItem(root)
  # 结点全部展开
  self.tree.expandAll()
   
  self.setCentralWidget(self.tree)
   
   
  if __name__ == '__main__':
  app = QApplication(sys.argv)
  tree = TreeWidgetDemo()
  tree.show()
  sys.exit(app.exec_())

运行结果:

06.PyQt5高级界面控------PyQt5编程开发

二、容器:装载更多的控件

1、QTabWidget

    它提供了一个选项卡和一个页面区域,默认显示第一个选项卡的页面。通过单击各选项卡可以查看对应的页面。常用方法:

    addTab():将一个控件添加到Tab控件的选项卡中

    insertTab():将一个Tab控件的选项卡插入到指定的位置

    removeTab():根据指定的索引删除Tab控件

    setCurrentIndex():设置当前可见的选项卡所在的索引

    setCurrentWidget():设置当前可见的页面

    setTabBar():设置选项卡栏的小控件

    setTabPosition():设置选项卡的位置  QTabWidget.North 显示在页面上方  QTabWidget.South 显示在页面下方,左右同理

    setTabText():定义Tab选项卡的显示值

    例子:

'''
  【简介】
  PyQt5中 QTabWidget 例子
 
 
  '''
   
  import sys
  from PyQt5.QtCore import *
  from PyQt5.QtGui import *
  from PyQt5.QtWidgets import *
   
  class TabDemo(QTabWidget):
  def __init__(self, parent=None):
  super(TabDemo, self).__init__(parent)
  self.tab1 = QWidget()
  self.tab2 = QWidget()
  self.tab3 = QWidget()
  self.addTab(self.tab1,"Tab 1")
  self.addTab(self.tab2,"Tab 2")
  self.addTab(self.tab3,"Tab 3")
  self.tab1UI()
  self.tab2UI()
  self.tab3UI()
  self.setWindowTitle("Tab 例子")
   
  def tab1UI(self):
  layout = QFormLayout()
  layout.addRow("姓名",QLineEdit())
  layout.addRow("地址",QLineEdit())
  self.setTabText(0,"联系方式")
  self.tab1.setLayout(layout)
   
  def tab2UI(self):
  layout = QFormLayout()
  sex = QHBoxLayout()
  sex.addWidget(QRadioButton(""))
  sex.addWidget(QRadioButton(""))
  layout.addRow(QLabel("性别"),sex)
  layout.addRow("生日",QLineEdit())
  self.setTabText(1,"个人详细信息")
  self.tab2.setLayout(layout)
   
  def tab3UI(self):
  layout=QHBoxLayout()
  layout.addWidget(QLabel("科目"))
  layout.addWidget(QCheckBox("物理"))
  layout.addWidget(QCheckBox("高数"))
  self.setTabText(2,"教育程度")
  self.tab3.setLayout(layout)
   
  if __name__ == '__main__':
  app = QApplication(sys.argv)
  demo = TabDemo()
  demo.show()
  sys.exit(app.exec_())

运行结果:

06.PyQt5高级界面控------PyQt5编程开发

2、QStackedWidget

    它是一个堆栈窗口的控件,可以填充一些小的控件,但同一时间只有一个小控件可以显示。QStackedWidget使用QStackedLayout布局。QStackedWidget控件与QTabWidget类似,可以有效地显示窗口中的控件。

例子:

'''
  【简介】
  PyQt5中 QStackedWidget 例子
 
 
  '''
   
  import sys
  from PyQt5.QtCore import *
  from PyQt5.QtGui import *
  from PyQt5.QtWidgets import *
   
  class StackedExample(QWidget):
  def __init__(self):
  super(StackedExample, self).__init__()
  self.setGeometry(300, 50, 10,10)
  self.setWindowTitle('StackedWidget 例子')
   
  self.leftlist = QListWidget ()
  self.leftlist.insertItem (0, '联系方式' )
  self.leftlist.insertItem (1, '个人信息' )
  self.leftlist.insertItem (2, '教育程度' )
  self.stack1= QWidget()
  self.stack2= QWidget()
  self.stack3= QWidget()
  self.stack1UI()
  self.stack2UI()
  self.stack3UI()
  self.Stack = QStackedWidget (self)
  self.Stack.addWidget (self.stack1)
  self.Stack.addWidget (self.stack2)
  self.Stack.addWidget (self.stack3)
  hbox = QHBoxLayout(self)
  hbox.addWidget(self.leftlist)
  hbox.addWidget(self.Stack)
  self.setLayout(hbox)
  self.leftlist.currentRowChanged.connect(self.display)
   
  def stack1UI(self):
  layout=QFormLayout()
  layout.addRow("姓名",QLineEdit())
  layout.addRow("地址",QLineEdit())
  self.stack1.setLayout(layout)
   
  def stack2UI(self):
  layout=QFormLayout()
  sex=QHBoxLayout()
  sex.addWidget(QRadioButton(""))
  sex.addWidget(QRadioButton(""))
  layout.addRow(QLabel("性别"),sex)
  layout.addRow("生日",QLineEdit())
  self.stack2.setLayout(layout)
   
  def stack3UI(self):
  layout=QHBoxLayout()
  layout.addWidget(QLabel("科目"))
  layout.addWidget(QCheckBox("物理"))
  layout.addWidget(QCheckBox("高数"))
  self.stack3.setLayout(layout)
   
  def display(self,i):
  self.Stack.setCurrentIndex(i)
   
  if __name__ == '__main__':
  app = QApplication(sys.argv)
  demo = StackedExample()
  demo.show()
  sys.exit(app.exec_())

运行结果:

06.PyQt5高级界面控------PyQt5编程开发

3、QDockWidget

    它是一个可以停靠在QMainWindow内的窗口控件,它可以保持在浮动状态或者在指定位置作为子窗口附加到主窗口中。QMainWindow类的主窗口对象保留一个用于停靠窗口的区域,这个区域在控件的*周围,QDockWidget控件在主窗口内可以移动到新的区域。QDockWidget类中的常用方法为:

    setWidget():在Dock窗口区域设置QWidget

    setFloating():设置Dock窗口是否可以浮动,如果设置为true,则表示可以浮动

    setAllowedAreas():设置窗口可以停靠的区域: LeftDockWidgetArea 左边停靠区域

                                                                              RightDockWidgetArea  右边停靠区域

                                                                              TopDockWidgetArea  顶部停靠区域

                                                                              BottomDockWidgetArea    底部停靠区域

                                                                              NoDockWidgetArea      不显示Widget

    setFeatures():设置停靠窗口的功能属性:  DockWidgetClosable  可关闭

                                                                       DockWidgetMovable   可移动

                                                                       DockWidgetFloatable   可漂浮

                                                                       DockWidgetVerticalTitleBar  在左边显示垂直的标签栏

                                                                       AllDockWidgetFeatures    具有前三种属性的所有功能

                                                                       NoDockWidgetFeatures    无法关闭,不能移动,不能漂浮

QDockWidget使用例子:

'''
  【简介】
  PyQt5中 QDockWidget 例子
 
 
  '''
   
  import sys
  from PyQt5.QtCore import *
  from PyQt5.QtGui import *
  from PyQt5.QtWidgets import *
   
  class DockDemo(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(False)
  self.setCentralWidget(QTextEdit())
  self.addDockWidget(Qt.RightDockWidgetArea, self.items)
  self.setLayout(layout)
  self.setWindowTitle("Dock 例子")
   
  if __name__ == '__main__':
  app = QApplication(sys.argv)
  demo = DockDemo()
  demo.show()
  sys.exit(app.exec_())
运行结果:

06.PyQt5高级界面控------PyQt5编程开发

4、多文档界面

    MDI(Multiple Document Interface,多文档界面)应用程序占用较少的内存资源,子窗口都可以放在主窗口容器中,这个容器控件被称为QMdiArea。QMdiArea控件通常占据在QMainWindow对象的中间位置,子窗口在这个区域是QMdiSubWindow类的实例,可以设置任何QWidget作为子窗口对象的内部控件,QMdiArea类和QMdiSubWindow类中的常用方法如下:

    addSubWindow():将一个小控件添加在MDI区域作为一个新的子窗口

    removeSubWindow():删除一个子窗口的小控件

    setActiveSubWindow():激活一个子窗口

    cascadeSubWindows():安排子窗口在MDI区域级联显示

    tileSubWindows():安排子窗口在MDI区域平铺显示

    closeActiveSubWindow():关闭活动的子窗口

    subWindowList():返回MDI区域的子窗口列表

    setWidget():设置一个小控件作为QMdiSubwindow实例对象的内部控件

例子:

'''
  【简介】
  PyQt5中 QMdiArea 例子
 
 
  '''
   
  import sys
  from PyQt5.QtCore import *
  from PyQt5.QtGui import *
  from PyQt5.QtWidgets import *
   
  class MainWindow(QMainWindow):
  count=0
  def __init__(self, parent=None):
  super(MainWindow, self).__init__(parent)
  self.mdi = QMdiArea()
  self.setCentralWidget(self.mdi)
  bar=self.menuBar()
  file=bar.addMenu("File")
  file.addAction("New")
  file.addAction("cascade")
  file.addAction("Tiled")
  file.triggered[QAction].connect(self.windowaction)
  self.setWindowTitle("MDI demo")
   
  def windowaction(self, q):
  print( "triggered")
   
  if q.text()=="New":
  MainWindow.count=MainWindow.count+1
  sub=QMdiSubWindow()
  sub.setWidget(QTextEdit())
  sub.setWindowTitle("subwindow"+str(MainWindow.count))
  self.mdi.addSubWindow(sub)
  sub.show()
  if q.text()=="cascade":
  self.mdi.cascadeSubWindows()
  if q.text()=="Tiled":
  self.mdi.tileSubWindows()
   
  if __name__ == '__main__':
  app = QApplication(sys.argv)
  demo = MainWindow()
  demo.show()
  sys.exit(app.exec_())
 

运行结果:

06.PyQt5高级界面控------PyQt5编程开发

5、QScrollBar

提供了水平或者垂直的滚动条,这样可以扩大当前窗口的有效装载面积,从而装载更多的控件。常用方法:

    valueChanged:当滑动条的值改变时发射该信号

    sliderMoved:当用户拖动滑动条时发射此信号

例子:

'''
  【简介】
  PyQt5中 QScrollBar 例子
 
 
  '''
   
  import sys
  from PyQt5.QtCore import *
  from PyQt5.QtGui import *
  from PyQt5.QtWidgets import *
   
  class Example(QWidget):
  def __init__(self):
  super(Example, self).__init__()
  self.initUI()
   
  def initUI(self):
  hbox = QHBoxLayout( )
  self.l1 = QLabel("拖动滑动条去改变颜色")
  self.l1.setFont(QFont("Arial",16))
  hbox.addWidget(self.l1)
  self.s1 = QScrollBar()
  self.s1.setMaximum(255)
  self.s1.sliderMoved.connect(self.sliderval)
  self.s2 = QScrollBar()
  self.s2.setMaximum(255)
  self.s2.sliderMoved.connect(self.sliderval)
  self.s3 = QScrollBar()
  self.s3.setMaximum(255)
  self.s3.sliderMoved.connect(self.sliderval)
  hbox.addWidget(self.s1)
  hbox.addWidget(self.s2)
  hbox.addWidget(self.s3)
  self.setGeometry(300, 300, 300, 200)
  self.setWindowTitle('QScrollBar 例子')
  self.setLayout( hbox )
   
  def sliderval(self):
  print( self.s1.value(),self.s2.value(), self.s3.value() )
  palette = QPalette()
  c = QColor(self.s1.value(),self.s2.value(), self.s3.value(),255)
  palette.setColor(QPalette.Foreground,c)
  self.l1.setPalette(palette)
   
  if __name__ == '__main__':
  app = QApplication(sys.argv)
  demo = Example()
  demo.show()
  sys.exit(app.exec_())

运行结果:

06.PyQt5高级界面控------PyQt5编程开发

三、多线程

    多线程技术涉及三种方法,一种是使用计时器模块QTimer;一种是使用多线程模块QThread;还有一种是使用事件处理的功能。

1、QTimer

    如果要在应用程序中周期性地进行某项操作,比如周期性地检查主机的CPU值,则需要用到QTimer(定时器),QTimer类提供了重复的和单次的定时器。要使用定时器,需要创建一个QTimer实例,将其timeout信号连接到相应的槽,并调用start()。然后,定时器会以恒定的间隔发出timeout信号。当窗口控件收到timeout信号后,它就会停止这个定时器。这是在图形用户界面中实现复制工作的一个典型方法,随着技术的进步,多线程在越来越多的平台上被使用,最终QTimer对象会被线程所替代。

    QTimer类中的常用方法: start(milliseconds):启动或重启定时器,时间间隔为毫秒。如果定时器已经运行,它将被停止并重新启动。如果singleShot信号为真,定时器将仅被激活一次

                                         Stop():停止定时器

    QTimer类中的常用信号:singleShot:在给定的时间间隔后调用一个槽函数时发射此信号

    timeout:当定时器超时时发射此信号

例子:

'''
  【简介】
  PyQT5中 QTimer例子
 
 
  '''
   
  from PyQt5.QtWidgets import QWidget, QPushButton , QApplication ,QListWidget, QGridLayout , QLabel
  from PyQt5.QtCore import QTimer ,QDateTime
  import sys
   
  class WinForm(QWidget):
   
  def __init__(self,parent=None):
  super(WinForm,self).__init__(parent)
  self.setWindowTitle("QTimer demo")
  self.listFile= QListWidget()
  self.label = QLabel('显示当前时间')
  self.startBtn = QPushButton('开始')
  self.endBtn = QPushButton('结束')
  layout = QGridLayout(self)
   
  # 初始化一个定时器
  self.timer = QTimer(self)
  # showTime()方法
  self.timer.timeout.connect(self.showTime)
   
  layout.addWidget(self.label,0,0,1,2)
  layout.addWidget(self.startBtn,1,0)
  layout.addWidget(self.endBtn,1,1)
   
  self.startBtn.clicked.connect( self.startTimer)
  self.endBtn.clicked.connect( self.endTimer)
   
  self.setLayout(layout)
   
  def showTime(self):
  # 获取系统现在的时间
  time = QDateTime.currentDateTime()
  # 设置系统时间显示格式
  timeDisplay = time.toString("yyyy-MM-dd hh:mm:ss dddd");
  # 在标签上显示时间
  self.label.setText( timeDisplay )
   
  def startTimer(self):
  # 设置计时间隔并启动
  self.timer.start(1000)
  self.startBtn.setEnabled(False)
  self.endBtn.setEnabled(True)
   
  def endTimer(self):
  self.timer.stop()
  self.startBtn.setEnabled(True)
  self.endBtn.setEnabled(False)
   
  if __name__ == "__main__":
  app = QApplication(sys.argv)
  form = WinForm()
  form.show()
  sys.exit(app.exec_())

运行结果:

06.PyQt5高级界面控------PyQt5编程开发

例二:

'''
  【简介】
  PyQT5中关闭应用例子
 
 
  '''
   
  import sys
  from PyQt5.QtWidgets import *
  from PyQt5.QtGui import *
  from PyQt5.QtCore import *
   
  if __name__ == '__main__':
  app = QApplication(sys.argv)
  label = QLabel("<font color=red size=128><b>Hello PyQT,窗口会在10秒后消失!</b></font>")
  label.setWindowFlags(Qt.SplashScreen|Qt.FramelessWindowHint)
  label.show()
   
  # 设置10s后自动退出
  QTimer.singleShot(10000, app.quit)
  sys.exit(app.exec_())

运行结果:

06.PyQt5高级界面控------PyQt5编程开发

2、QThread

    它是Qt线程类中最核心的底层类。要使用QThread开始一个线程,可以创建它的一个子类,然后覆盖其QThread.run()函数;PyQt的线程使用非常简单-------建立一个自定义的类(如Thread),使它继承自QThread,并实现其run()方法即可。

    在使用线程时可以直接得到Thread实例,调用其start()函数即可启动线程。线程启动之后,会自动调用其实现的run方法,该方法就是线程的执行函数。

    业务的线程任务就写在run()函数中,当run()推出之后线程基本就结束了。QThread有started和finished信号,可以为这两个信号指定槽函数,在线程启动和结束时执行一段代码进行资源的初始化和释放操作。更灵活的使用方法是,在自定义的QThread实例中自定义信号,并将信号连接到指定的槽函数,当满足一定条件后发射该信号。

    QThread类中的常用方法:

    start():启动线程

    wait():阻止线程

    sleep():强制当前线程睡眠

    QThread类中的常用信号:

    started:在开始执行run()函数之前,从相关线程发射该信号

    finished:当程序完成业务逻辑时,从相关线程发射该信号

    QThread实例:当在窗口中显示的数据比较简单时,可以把读取数据的业务逻辑放在窗口的初始化代码中;但如果读取数据的时间比较长,比如网络请求数据的时间比较长,则可以把这部分逻辑放在QThread线程中,实现界面的数据显示和数据读取的分离,以满足MVC(模型---视图---控制器)设计模式的要求。

    例子:

'''
  【简介】
  PyQT5中 QThread 例子
 
 
  '''
   
  from PyQt5.QtCore import *
  from PyQt5.QtGui import *
  from PyQt5.QtWidgets import *
  import sys
   
  class MainWidget(QWidget):
  def __init__(self,parent=None):
  super(MainWidget,self).__init__(parent)
  self.setWindowTitle("QThread 例子")
  self.thread = Worker()
  self.listFile = QListWidget()
  self.btnStart = QPushButton('开始')
  layout = QGridLayout(self)
  layout.addWidget(self.listFile,0,0,1,2)
  layout.addWidget(self.btnStart,1,1)
  self.btnStart.clicked.connect( self.slotStart )
  self.thread.sinOut.connect(self.slotAdd)
   
  def slotAdd(self,file_inf):
  self.listFile.addItem(file_inf)
   
  def slotStart(self):
  self.btnStart.setEnabled(False)
  self.thread.start()
   
  class Worker(QThread):
  sinOut = pyqtSignal(str)
   
  def __init__(self,parent=None):
  super(Worker,self).__init__(parent)
  self.working = True
  self.num = 0
   
  def __del__(self):
  self.working = False
  self.wait()
   
  def run(self):
  while self.working == True:
  file_str = 'File index {0}'.format(self.num)
  self.num += 1
  # 发出信号
  self.sinOut.emit(file_str)
  # 线程休眠2秒
  self.sleep(2)
   
  if __name__ == "__main__":
  app = QApplication(sys.argv)
  demo = MainWidget()
  demo.show()
  sys.exit(app.exec_())

运行结果:

06.PyQt5高级界面控------PyQt5编程开发

但是在PyQt中所有的窗口都在UI主线程中(就是执行了QApplication.exec()的线程),在这个线程中执行耗时操作会阻塞UI线程,从而让窗口停止响应。如果窗口长时间没有响应,则会影响用户体验,更严重的会导致程序崩溃。所以,为了避免出现这样的问题,要使用QThread开启一个新的线程,在这个线程中完成耗时的操作。例子如下:

'''
  【简介】
  PyQT5中 QTimer例子
 
 
  '''
   
  import sys
  from PyQt5.QtCore import *
  from PyQt5.QtGui import *
  from PyQt5.QtWidgets import *
   
  global sec
  sec=0
   
  class WorkThread(QThread):
  trigger = pyqtSignal()
  def __int__(self):
  super(WorkThread,self).__init__()
   
  def run(self):
  for i in range(2000000000):
  pass
   
  # 循环完毕后发出信号
  self.trigger.emit()
   
  def countTime():
  global sec
  sec += 1
  # LED显示数字+1
  lcdNumber.display(sec)
   
  def work():
  # 计时器每秒计数
  timer.start(1000)
  # 计时开始
  workThread.start()
  # 当获得循环完毕的信号时,停止计数
  workThread.trigger.connect(timeStop)
   
  def timeStop():
  timer.stop()
  print("运行结束用时",lcdNumber.value())
  global sec
  sec=0
   
  if __name__ == "__main__":
  app = QApplication(sys.argv)
  top = QWidget()
  top.resize(300,120)
   
  # 垂直布局类QVBoxLayout
  layout = QVBoxLayout(top)
  # 加个显示屏
  lcdNumber = QLCDNumber()
  layout.addWidget(lcdNumber)
  button = QPushButton("测试")
  layout.addWidget(button)
   
  timer = QTimer()
  workThread = WorkThread()
   
  button.clicked.connect(work)
  # 每次计时结束,触发 countTime
  timer.timeout.connect(countTime)
   
  top.show()
  sys.exit(app.exec_())

运行结果:

06.PyQt5高级界面控------PyQt5编程开发

3、事件处理

    PyQt为事件处理提供了两种机制:高级的信号与槽机制,以及低级的事件处理程序。今天就学低级的事件处理程序,也就是processEvents()函数的使用方法,它的作用是处理事件,简单地说,就是刷新页面。

    对应执行很耗时的程序来说,由于PyQt需要等待程序执行完毕才能进行下一步,这个过程表现在界面上就是卡顿;而如果在执行这个耗时程序时不断地运行QApplication.processEvents(),那么就可以实现一边执行耗时程序,一边刷新页面的功能,给人的感觉就是程序运行很流畅。因此QApplication.processEvents()的使用方法就是,在主函数执行耗时操作的地方,加入QApplication.processEvents().例子如下:

'''
  【简介】
  PyQT5中实时刷新界面例子
 
 
  '''
   
  from PyQt5.QtWidgets import QWidget, QPushButton , QApplication ,QListWidget, QGridLayout
  import sys
  import time
   
  class WinForm(QWidget):
   
  def __init__(self,parent=None):
  super(WinForm,self).__init__(parent)
  self.setWindowTitle("实时刷新界面例子")
  self.listFile= QListWidget()
  self.btnStart = QPushButton('开始')
  layout = QGridLayout(self)
  layout.addWidget(self.listFile,0,0,1,2)
  layout.addWidget(self.btnStart,1,1)
  self.btnStart.clicked.connect( self.slotAdd)
  self.setLayout(layout)
   
  def slotAdd(self):
  for n in range(10):
  str_n='File index {0}'.format(n)
  self.listFile.addItem(str_n)
  QApplication.processEvents()
  time.sleep(1)
   
  if __name__ == "__main__":
  app = QApplication(sys.argv)
  form = WinForm()
  form.show()
  sys.exit(app.exec_())

运行结果:

06.PyQt5高级界面控------PyQt5编程开发

四、网页交互

    略~