使用 PyQt 工具包开发 PyQt 程序总结

发布于 2024-01-24 12:52:37 字数 20327 浏览 16 评论 0

python 支持多种图形界面的第三方库。包括:

  • TK 图形库,由 Tcl 语言开发的。python 调用内置 tkinter 库。
  • wxWidgets 图形库,由 C++语言开发。Python 第三方库 wxPython 封装了此图形库。
  • Qt 非常强大的应用程序开发框架,可开发 GUI 或非 GUI 程序。python 第三方库 PyQt。
  • GTK 对应 python 的第三库为 PyGTK。

Qt 概念

Qt 是一个由 C++编写的跨平台的应用程序开发框架。可以用来开发 GUI 程序,也可以用来开发非 GUI 程序。目前 Qt 有两种版本,一种是商业版本(付费使用),另一种则是基于(L)GPL v3 的开源版本。

Qt 具体在某些方面的应用,大家可以访问 Qt 官网) 进行查看。

PyQt 概念

Qt 和 PyQt 有什么区别?简而言之,PyQt 是 Qt 的一个 wrapper(封装)。PyQt 为 python 开发 GUI 程序提供了解决方案,同样 PyQt 也是跨平台的,支持 Linux、Windows、Mac OS。从 PyQt4 开始,所有平台上均支持 GPL(General Public License) 协议即开源协议。

PyQt 官方网站请 点击 。PyQt4 官方文档请 点击

版本

目前有 PyQt4 和 PyQt5 两种版本,且两者不兼容。PyQt4 在官网介绍说明中,未来将不会得到支持,所以 PyQt5 是未来的一个趋势。当然目前 PyQt4 使用最为广泛。

本文主要以 PyQt4 进行介绍。

安装

PyQt 安装这一块,可能比较复杂。需要下载包手动安装。工具包 下载地址

首先 PyQt 工具包版本需要与 Python 版本进行匹配。版本位数也必须要匹配,比如 python 解释器是 32 位,那么工具包也必须是 32 位的。这里推荐大家版本都采用 64 位。

组件模块

PyQt4 为跨平台的工具包,它包括了 300 多个类和 6000 多个方法。由于过多的类和方法,整个工具库被划分成了多个模块。不同模块主要实现不同的功能,这一部分大家主要了解以下模块的主要作用。并学习掌握几个关键模块。

具体模块如下:

  • QtGui 模块包括图形化窗口组件和及相关类。包括如按钮、窗体、状态栏、滑块、位图、颜色、字体等等。
  • QtCore 模块包括了核心的非 GUI 功能,该模块用来对时间、文件、目录、各种数据类型、流、网址、媒体类型、线程或进程进行处理。
  • QtHelp 模块包含了用于创建和查看可查找的文档的类。
  • QtNetwork 模块包括网络编程的类。这些类可以用来编写 TCP/IP 和 UDP 的客户端和服务器。它们使得网络编程更容易和便捷。
  • QtOpenGL 模块使用 OpenGL 库来渲染 3D 和 2D 图形。该模块使得 Qt GUI 库和 OpenGL 库无缝集成。
  • QtScript 模块包含了使 PyQt 应用程序使用 JavaScript 解释器编写脚本的类。
  • QtSql 模块提供操作数据库的类。
  • QtSvg 模块提供了显示 SVG 文件内容的类。可缩放矢量图形(SVG) 是一种用 XML 描述二维图形和图形应用的语言。
  • QtTest 模块包含了对 PyQt 应用程序进行单元测试的功能。(PyQt 没有实现完全的 Qt 单元测试框架,相反,它假设使用标准的 Python 单元测试框架来实现模拟用户和 GUI 进行交互。)
  • QtWebKit 模块实现了基于开源浏览器引擎 WebKit 的浏览器引擎。
  • QtXml 包括处理 XML 文件的类,该模块提供了 SAX 和 DOM API 的接口。
  • QtAssistant 模块包含的类允许集成 Qt Assistant 到 PyQt 应用程序中,提供在线帮助。
  • QtDesigner 模块包含的类允许使用 PyQt 扩展 Qt Designer。
  • uic 模块包含的类用来处理.ui 文件,该文件由 Qt Designer 创建,用于描述整个或者部分用户界面。它包含的加载.ui 文件和直接渲染以及从.ui 文件生成 Python 代码为以后执行的类。

常用组件

以下描述组件均为 GUI 界面的组件,属于 QtGui 模块。重点关注几个常用组件的信号和方法。

1、按键 QPushButton

# 初始化 button 类,得到一个按键对象
ok_button = QtGui.QPushButton('OK', widget)

信号:

  • clicked():按键被点击后触发的信号;
  • pressed():按键倍按下触发的信号;
  • released():按键被释放(抬起)时触发的信号;

构造方法:

# 添加一个按键,并设置图标和文本
__init__(self, QIcon, QString_text, QWidget parent = None)

2、行编辑框 QLineEdit

# 初始化类,得到对象
useredit = QtGui.QLineEdit(widget)

信号:

  • cursorPositionChanged(int,int):光标位置改变触发;
  • editingFinished():编辑完成后触发的信号(编辑框失去光标);
  • textChanged(const QString&):文本内容改变时触发的信号;

构造方法:

# 生成一个行编辑框
__init__(self, QWidget parent = None)
# 生成一个带初始值的行编辑框
__init__(self, QString contents, QWidget parent = None)

方法:

  • clear(self):清除编辑框内容;
  • setText(self, QString):设置编辑框的内容;
  • text(self):取编辑框内的文本内容;
  • setMaxLength(self, int):设置编辑框能够输入的最大长度

3、文本编辑框 QTextEdit

# QTextEdit 类
logedit = QtGui.QTextEdit(widget)

信号:

  • cursorPositionChanged():光标位置改变触发;
  • textChanged(const QString&):文本内容改变时触发的信号;

构造方法:

# 生成一个文本编辑框
__init__(self, QWidget parent = None)
# 生成一个有初始文本的文本编辑框
__init__(self, QString_text, QWidget parent = None)

方法:

  • clear(self):清除编辑框内容;
  • setText(self, QString):设置编辑框的内容;
  • toPlainText(self):以文本的格式取编辑框内的文本内容;
  • toHtml(self):以 HTML 的格式取编辑框内的文本内容;

4、标签 QLabel

userlabel = QtGui.QLabel('label', widget)

构造方法:

__init__(self, QWidget parent = None, Qt.WindowFlags flags = 0):
# 带值的标签
__init__(self, QString_text, QWidget parent = None, Qt.WindowFlags flags = 0)

方法:

  • clear(self):清除编辑框内容;
  • setText(self, QString):设置编辑框的内容;
  • text(self):取编辑框内的文本内容;

5、下拉框 QComboBox

# 得到下拉框对象
select_box= QtGui.QComboBox(widget)

信号:

  • currentIndexChanged(int):选择项改变时触发,返回当前选项序号
  • currentIndexChanged(const QString&):选择项改变时触发,返回当前选项文本
  • activated(int):当用户选择下拉列表的项时触发,即使选择项未改变
  • activated(const QString&):当用户选择下拉列表的项时触发,即使选择项未改变

构造方法:

__init__(self, QWidget parent = None)

方法:

  • addItem(self, QString text, QVariant userData = QVariant()):给下拉列表添加下拉项;
  • addItems(self, QStringList texts):给下拉列表添加多个下拉项;
  • currentIndex(self):返回当前下拉列表的下拉项序号;
  • currentText(self):返回当前下拉列表的下拉项文本;
  • setItemText(self, int index, QString text):设置下拉项的文本

6、树结构 QTreeWidget

# 树结构对象
casetree = QtGui.QTreeWidget(self.centralwidget)

信号:

  • itemClicked(QTreeWidgetItem*,int):选项被点击时触发
  • itemCollapsed(QTreeWidgetItem*):子选项被隐藏时触发
  • itemDoubleClicked(QTreeWidgetItem*,int):选项被双击时触发
  • itemExpanded(QTreeWidgetItem*):子选项被展示时触发

构造方法:

__init__(self, QWidget parent = None)

方法:

  • setColumnCount(self, int columns):设置树结构的列数;
  • setHeaderLabels(self, QStringList labels):设置列标签;
  • headerItem(self):返回用于树窗口小部件标题的项目;

7、树目录 QTreeWidgetItem

root= QtGui.QTreeWidgetItem(self.casetree)

构造方法:

__init__(self, int type = QTreeWidgetItem.Type)
__init__(self, QStringList strings, int type = QTreeWidgetItem.Type)
__init__(self, QTreeWidget parent, int type = QTreeWidgetItem.Type)
__init__(self, QTreeWidget parent, QStringList strings, int type = QTreeWidgetItem.Type)
__init__(self, QTreeWidget parent, QTreeWidgetItem preceding, int type = QTreeWidgetItem.Type)
__init__(self, QTreeWidgetItem parent, int type = QTreeWidgetItem.Type)
__init__(self, QTreeWidgetItem parent, QStringList strings, int type = QTreeWidgetItem.Type)
__init__(self, QTreeWidgetItem parent, QTreeWidgetItem preceding, int type = QTreeWidgetItem.Type)
__init__(self, QTreeWidgetItem other)

方法:

  • addChild(self, QTreeWidgetItem child):添加子节点;
  • checkState(self, int column):检查点击状态;
  • setCheckState(self, int column, Qt.CheckState state):设置选项的选中状态,第二个参数为 QT.Checked 表示选中,Qt.UnChecked 表示未选中;
  • setData(self, int column, int role, QVariant value):设置选项的角色值;
  • setText(self, int column, QString atext):设置选项的文本内容

界面布局

这一块大家了解一下即可。基本上 GUI 界面都是通过绘图得到的。

1、绝对定位

用像素(px) 指定每个组件(控件) 的大小和位置。

# 使用 move 方法确定组件的位置
move(x, y)
# 开始的两个参数是窗体的 x 和 y 的位置,a、b 为组件的宽度、高度
setGeometry(x, y, a, b)

2、框布局

基本的布局类是 QHBoxLayout 和 QVBoxLayout ,它们可以横向和纵向排列窗口组件。QHBoxLayout 布局类为水平布局类,在该布局中的组件呈水平排列。QVBoxLayout 布局类为垂直布局类,在该布局中的组件呈垂直排列。框布局就是结合水平布局与垂直布局,使组件能够二维分布

import sys
from PyQt4 import QtGui

class MainWindow(QtGui.QWidget):
  """docstring for ClassName"""
  def __init__(self, parent=None):
    super(MainWindow, self).__init__()
    self.initUI()
    
  def initUI(self):
    okButton = QtGui.QPushButton("OK")
    cancelButton = QtGui.QPushButton("Cancel")
    hbox = QtGui.QHBoxLayout()
    hbox.addStretch(1)
    hbox.addWidget(okButton)
    hbox.addStretch(1)
    hbox.addWidget(cancelButton)
    vbox = QtGui.QVBoxLayout()
    vbox.addStretch(1)
    vbox.addLayout(hbox)
    vbox.addStretch(1)
    self.setLayout(vbox)
    self.setWindowTitle('box layout')

if __name__ == "__main__":
  app = QtGui.QApplication(sys.argv)
  window = MainWindow()
  window.show()
  sys.exit(app.exec_())

3、网格布局

最常用的布局类是网格布局,网格布局把空间划分成行和列,一般使用 QGridLayout 类来创建网格布局。布局类型设置好以后使用 addWidget() 方法来把窗口组件加到网格中,参数是部件(widget),行(row)和列(column)数字。

  • addWidget(widget-obj):给布局添加组件,将我们需要用到的控件加入到布局中;
  • addLayout(Layout-obj):给布局添加另一个布局,使用框布局通常需要用该方法将水平布局和垂直布局结合;

代码实例:

import sys
from PyQt4 import QtGui

class MainWindow(QtGui.QWidget):
  """docstring for ClassName"""
  def __init__(self, parent=None):
    super(MainWindow, self).__init__()
    self.initUI()
    
  def initUI(self):
    self.setWindowTitle('grid layout')
    names = ['Cls', 'Bck', '', 'Close', '7', '8', '9', '/',
         '4', '5', '6', '*', '1', '2', '3', '-',
         '0', '.', '=', '+']
    grid = QtGui.QGridLayout()
    j = 0
    pos = [(0, 0), (0, 1), (0, 2), (0, 3),
         (1, 0), (1, 1), (1, 2), (1, 3),
         (2, 0), (2, 1), (2, 2), (2, 3),
         (3, 0), (3, 1), (3, 2), (3, 3 ),
         (4, 0), (4, 1), (4, 2), (4, 3)]
    for i in names:
      button = QtGui.QPushButton(i)
      if j == 2:
        grid.addWidget(QtGui.QLabel(''), 0, 2)
      else:
        grid.addWidget(button, pos[j][0], pos[j][1])
      j = j + 1
    self.setLayout(grid)

if __name__ == "__main__":
  app = QtGui.QApplication(sys.argv)
  window = MainWindow()
  window.show()
  sys.exit(app.exec_())

GUI 页面

我们将利用 QtGui 模块实现生成 GUI 界面,学习常用的几个类。

实例一:学习了解几个方法

#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui

def main():
  # 创建 app 对象,每个 PyQt 程序都必须创建一个 Application 对象
  # sys.argv 获取参数列表
  app = QtGui.QApplication(sys.argv)
  # w 为 QWidget 类的对象,QWidget 窗口组件是 PyQt4 所有用户界面的基类
  w =QtGui.QWidget()
  # 初始化界面的大小,以下单位为像素(px)
  w.resize(250, 150)
  # 移动窗口的位置
  w.move(300, 300)
  # 设置界面标题
  w.setWindowTitle('Simple GUI')
  # 设置应用程序图标
  w.setWindowIcon(QtGui.QIcon('icons/web.png'))
  # show() 方法将 GUI 界面显示在屏幕上
  w.show()
  # 退出循环时,调用 exit() 方法关闭
  sys.exit(app.exec_())

if __name__ == '__main__':
  main()

实例二:了解事件和 QMessageBox

# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui

class MainWindow(QtGui.QMainWindow):
  """主 GUI 界面窗口"""
  def __init__(self, parent=None):
    # 继承父类的构造方法,也可称之为超类
    super(MainWindow, self).__init__()
    # setGeometry() 方法定义了窗体在屏幕上的位置,并设置窗体的大小。
    # 开始的两个参数是窗体的 x 和 y 的位置,后面两个为 GUI 界面的宽度、高度
    self.setGeometry(200,200,600,500)
    # 设置标题
    self.setWindowTitle('test')
    # 气泡提示
    self.setToolTip('This is a <b>QWidget</b> widget.')
    # 设置字体
    # QtGui.QToolTip.setFont(QtGui.QFont('OldEnglish', 10))

  def closeEvent(self, event):
    """
    关闭 GUI 界面时,将会产生一个 QCloseEvent 事件。
    这里重写了 closeEvent 方法,实现关闭窗口时需要确认。改变了组件的行为。
    """
    reply = QtGui.QMessageBox.question(self,'Message','Are you sure to  quit?',QtGui.QMessageBox.Yes,QtGui.QMessageBox.No)
    if reply == QtGui.QMessageBox.Yes:
      event.accept()
    else:
      event.ignore()

if __name__ == '__main__':
  app = QtGui.QApplication(sys.argv)
  window = MainWindow()
  window.show()
  sys.exit(app.exec_())

实例三:

学习主 GUI 界面的状态栏、菜单栏、工具栏。工具栏一般不常用,常用的是另外两个。

注意:QMainWindow 类才有状态栏、菜单栏、工具栏。QWidget 与 QDialog 类型的窗口都不能这样使用。

# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui, QtCore

class MainWindow(QtGui.QMainWindow):
  """主 GUI 界面窗口"""
  def __init__(self, parent=None):
    # 继承父类的构造方法
    super(MainWindow, self).__init__()
    self.resize(600,500)
    self.setWindowTitle('Test')
    # 调用 QMainWindow 的 statusBar() 方法得到状态栏
    # 调用 showMessage() 方法显示状态信息
    self.statusBar().showMessage('Ready')

    # 定义一个 exit 的动作,设置图标和名字
    exit = QtGui.QAction(QtGui.QIcon(''),'Exit',self) 
    # 设置动作的快捷键
    exit.setShortcut('Ctrl+Q')
    # 状态栏显示 exit 动作提示信息
    exit.setStatusTip('Exit the Application') 
    # connect() 方法连接信号和槽函数
    self.connect(exit, QtCore.SIGNAL('triggered()'), QtCore.SLOT('close()'))
    # 调用 menuBar() 方法得到菜单栏
    menu = self.menuBar()
    # 调用 addMenu() 方法得到菜单项
    tools = menu.addMenu('&Tools')
    # 添加动作到菜单
    tools.addAction(exit)
    
    # 通过 addToolBar() 方法得到工具栏,工具栏一般不常用。
    self.toolbar = self.addToolBar('GoBack')
    #初始化一个动作
    goback = QtGui.QAction(QtGui.QIcon(''),'goback',self)
    #设置动作的快捷方式
    goback.setShortcut('Ctrl+D')
    #将动作添加到工具栏
    self.toolbar.addAction(goback)   


if __name__ == '__main__':
  app = QtGui.QApplication(sys.argv)
  window = MainWindow()
  window.show()
  sys.exit(app.exec_())

事件、信号与槽

这部分是 PyQt 程序一个核心部分。开发 PyQt 程序必须要掌握理解以下概念

事件

事件(Events)是 GUI 程序中很重要的一部分。它由用户或系统产生。当我们调用程序的 exec_() 方法时,程序就会进入主循环中。主循环捕获事件并将它们发送给相应的对象进行处理,事件往往伴随着一个信号的发生,或一个信号的处理。

这里事件(Events)包括鼠标点击、键盘按键输入等事件。

#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui, QtCore

class KeyExample(QtGui.QWidget):

  def __init__(self):
    super(KeyExample, self).__init__()

    self.setWindowTitle('Escape')
    self.resize(500, 500)

  def keyPressEvent(self, event):
    if event.key() == QtCore.Qt.Key_Escape:
      self.close()

if __name__ == "__main__":
  app = QtGui.QApplication(sys.argv)
  ex = KeyExample()
  ex.show()
  sys.exit(app.exec_())

信号与槽

当用户单击一个按钮,拖动一个滑块或进行其它动作时,相应的信号就会被触发。除此之外,信号还可以因为环境的变化而被发射。比如一个运行的时钟将会发射时间信号等。而所谓的槽则是一个方法(函数),该方法将会响应它所连接的信号。在 Python 中,槽可以是任何可以被调用的对象。槽一般为事件处理函数,专门用于处理某个信号。

在 PyQt 中,通过 connect() 方法连接信号与槽函数。此方法一般传入的参数为发送信号的对象、信号、对信号作出反应的方法(槽函数)。

connect(sender, QtCore.SIGNAL('clicked()'), revicer, QtCore.SLOT())

我们来看一个信号与槽的代码实例,目前我们用的最多就是 button 按钮的信号(clicked())。

# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui, QtCore

class ButtonExample(QtGui.QMainWindow):

  def __init__(self):
    super(ButtonExample, self).__init__()

    self.initUI()

  def initUI(self):
    button1 = QtGui.QPushButton("Button 1", self)
    button1.move(30, 50)

    button2 = QtGui.QPushButton("Button 2", self)
    button2.move(150, 50)
		# 连接信号与槽函数
    self.connect(button1, QtCore.SIGNAL('clicked()'),
      self.buttonClicked)
		
    self.connect(button2, QtCore.SIGNAL('clicked()'),
      self.buttonClicked)

    self.statusBar().showMessage('Ready')
    self.setWindowTitle('Event sender')
    self.resize(290, 150)

  def buttonClicked(self):
    """自定义槽函数,对信号作出反应"""
    # sender() 方法获取产生信号的对象
    sender = self.sender()
    self.statusBar().showMessage(sender.text() + ' was pressed')

if __name__ == '__main__':
  app = QtGui.QApplication(sys.argv)
  button = ButtonExample()
  button.show()
  sys.exit(app.exec_())

自定义信号

当然,我们也可以自定义信号。自定义信号不仅可以用于改变页面的显示状态,还可用于 GUI 线程与逻辑线程之间的数据传递。

# 创建一个不传递参数的信号
self.mysignal = QtCore.SIGNAL('bigthan10()')   
# 使用 emit() 方法发送信号
self.emit(self.mysignal)                     
# 创建一个传递参数的信号,参数类型为 int
self.mysignal = QtCore.pyqtSignal(int)
# 发送信号
self.mysignal.emit(20)

注意:使用自定义的槽函数处理自定义带传递参数的信号时,槽函数的参数与信号的参数必须保持一致(参数类型、参数个数、参数顺序)。

# -*- coding: utf-8 -*-
import sys
import time
from PyQt4 import QtGui, QtCore

class MainWindow(QtGui.QMainWindow):
  # 定义一个信号,信号不能定义在构造函数中,否则会报错
  mysignal = QtCore.pyqtSignal(str)
  def __init__(self):
    
    super(MainWindow,self).__init__()
    self.setGeometry(100,100,500,500)
    self.setWindowTitle('test')
    #self.setWindowIcon(QtGui.QIcon('C:\Users\Administrator\cut.png'))
    self.statusbar =self.statusBar()   #创建一个状态栏
    self.mysignal.connect(self.statusMessage)   #连接信号与槽函数
    date =time.ctime()  
    self.mysignal.emit(str(date))  #发射信号

  def statusMessage(self,date):
    # 自定义槽函数  
    self.statusbar.showMessage("now is %s!"%date)

if __name__ == '__main__':
  app = QtGui.QApplication(sys.argv)
  window = MainWindow()
  window.show()
  sys.exit(app.exec_())

画图

此部分为开发 PyQt 程序的核心部分。

前面我们介绍了 GUI 界面的相关组件、以及如何通过代码实现得到一个 GUI 界面。对于简单的图形界面,我们可以通过编写源码实现。但是如果图形界面过于复杂时,此时通过编码方式生成图形界面,工作量是非常巨大。此时我们可以通过 PyQt 工具包的 Designer 工具设计图形界面,保存得到.ui 文件,然后通过命令得到此 GUI 界面的 python 源码。

pyuic4 gui.ui > gui.py

现场演示如何使用此工具。

Designer 工具

1、组件栏:显示组件,供用户选择

2、主界面栏:显示主界面,相当与一个画布,可以在上面设计我们需要的页面

3、对象编辑栏:包括几个部分

  • 对象查看器:查看当前页面上存在的对象以及层次结构,显示对象名与对象类型,我们可以在这里修改对象名;
  • 属性编辑器:用于编辑对象的属性信息,在页面或对象查看器上选择对象,然后在属性编辑器上就能查看或修改到该对象所拥有的属性;
  • 资源浏览器:查看可用资源;
  • 信号/槽编辑器:创建信号与槽的关系,可以指定到某个对象
  • 动作编辑器:编辑动作,可添加到菜单栏或工具栏
import sys
from PyQt4 import QtGui,QtCore
from gui import Ui_MainWindow

class MainWindoW(QtGui.QMainWindow):
  """导入 gui.py 得到图形界面"""
  def __init__(self):
    super(MainWindoW, self).__init__()
    self.ui = Ui_MainWindow()
    self.ui.setupUi(self)

if __name__ == "__main__":
  app = QtGui.QApplication(sys.argv)
  wm = MainWindoW()
  wm.show()
  sys.exit(app.exec_())

多线程

此部分为图形化编程核心部分。

在 GUI 编程中,由于主界面是一个无限循环,且一直监听事务的发生,所以如果在主 UI 线程中做一些耗时的操作,会导致线程阻塞卡死,所以 PyQt 编程需要将主 UI 线程与逻辑线程分离,将一些耗时的操作都放在子线程里执行,主线程与子线程之间的数据传递通过自定义信号实现,PyQt 中定义的线程管理类为位于 QtCore 包的 QThread 类。

线程管理类 QThread

首先我们先学习 QThread 类有哪些方法。

1、信号

  • finished() 当线程执行完成触发该信号
  • started() 当线程开始时触发该信号
  • terminated() 当线程被中断停止时触发该信号

2、方法

  • __init__(self, QObject parent = None) parent 参数为父类线程的窗口类
  • quit(self) 终止线程执行
  • terminate(self) 终止线程,可能立即终止,也不能不会立即终止。
  • wait(self, int msecs = ULONG_MAX) 线程睡眠,等待
  • start(self) 拉起线程,并执行。
  • run(self) 线程主体函数,调用 start() 方法后,便会执行 run() 方法中的代码。一般逻辑处理代码均写在 run() 函数中
  • currentThread() 返回当前的线程对象
  • currentThreadId() 返回当前线程 Id

线程之间数据传递

1、通过 PyQt 中信号与槽的机制传递数据。

2、通过自定义的公共配置文件传递数据(如 config.ini)。

编写一个子线程

继承 QThread 类,重写 run 方法。

代码实例如下:

# -*- coding: utf-8 -*-
import sys, time
from PyQt4 import QtGui, QtCore
from PyQt4.QtGui import QPushButton, QLineEdit

class TimeThread(QtCore.QThread):
  """工作线程"""
  # 自定义信号,指定参数类型为 str
  signal_time = QtCore.pyqtSignal(str) 
 
  def __init__(self, parent=None):
    super(TimeThread, self).__init__(parent)

  def start_timer(self):
    self.start()

  def stop_timer(self):
    self.terminate()
    self.wait()

  def run(self):
    while True:
      print("Working", self.thread())
      print(time.ctime(),type(time.ctime()))
      # 发送信号,并携带参数值
      self.signal_time.emit(time.ctime())
      self.sleep(1)


class TimeWindow(QtGui.QMainWindow):
  def __init__(self):
    super(TimeWindow, self).__init__()

    self.init_ui()
    # 实例化子线程
    self.timer_t = TimeThread()
    # 信号连接槽函数
    self.timer_t.signal_time.connect(self.update_timer_tv)

  def init_ui(self):
    """生成 GUI 界面"""
    self.resize(300, 300)
    self.setWindowTitle('Time Clock')
    self.statusBar().showMessage('Ready')
    # 初始化行标签对象
    self.timer_tv = QLineEdit(self)
    self.timer_tv.setText("Wait")
    self.timer_tv.setGeometry(15, 15, 270, 25)
    # self.timer_tv.move(15, 15)

    lable1 = QtGui.QLabel('Current Time',self)
    lable1.move(150,100)

    # 初始化设置 Quit 按键对象
    stop_btn = QPushButton('Stop', self)
    stop_btn.setToolTip('Click to Stop')
    stop_btn.move(150, 150)
    # 连接 clicked 信号和槽函数
    self.connect(stop_btn, QtCore.SIGNAL("clicked()"), self.click_stop_button)

    # 初始化设置 start 按键对象
    start_btn = QPushButton('Start', self)
    start_btn.setToolTip("Click to start")
    start_btn.move(50, 150)
    # 连接 clicked 信号和槽函数
    self.connect(start_btn, QtCore.SIGNAL("clicked()"), self.click_start_button)

  def click_start_button(self):
    """槽函数拉起执行子线程"""
    self.timer_t.start_timer()
    self.statusBar().showMessage('Go')

  def click_stop_button(self):
    """槽函数终止子线程"""
    self.timer_t.stop_timer()
    self.statusBar().showMessage('Ready')

  def update_timer_tv(self, text):
    # 槽函数
    self.timer_tv.setText(text)


if __name__ == "__main__":
  app = QtGui.QApplication(sys.argv)
  window = TimeWindow()
  window.show()
  sys.exit(app.exec_())

开发 PyQt 程序

开发过程

  1. 确认需求
  2. 画图得到 gui.ui 文件,通过命令转换为 python 源码
  3. 编写主界面源码,得到界面
  4. 定义 config.ini 文件用来保存 GUI 界面的参数信息
  5. 编写后端代码(线程类)
  6. 连接信号和槽函数
  7. 调试运行

注意事项

  1. 安装 PyQt 时,注意版本之间的对应关系(包括位版本,如 32 位、64 位)。
  2. 编写线程代码时,注意线程卡死问题。
  3. GUI 界面参数传递到后台,注意参数的类型和值。一般的,都需要对参数进行处理。

    (这里推荐 python 内置函数 eval())

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

甜是你

暂无简介

0 文章
0 评论
24 人气
更多

推荐作者

我们的影子

文章 0 评论 0

素年丶

文章 0 评论 0

南笙

文章 0 评论 0

18215568913

文章 0 评论 0

qq_xk7Ean

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文