添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
  • 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

    1
    2
    # 初始化button类,得到一个按键对象
    ok_button = QtGui.QPushButton('OK', widget)
  • clicked():按键被点击后触发的信号;
  • pressed():按键倍按下触发的信号;
  • released():按键被释放(抬起)时触发的信号;
  • 构造方法:

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

    2、行编辑框QLineEdit

    1
    2
    # 初始化类,得到对象
    useredit = QtGui.QLineEdit(widget)
  • cursorPositionChanged(int,int):光标位置改变触发;
  • editingFinished():编辑完成后触发的信号(编辑框失去光标);
  • textChanged(const QString&):文本内容改变时触发的信号;
  • 构造方法:

    1
    2
    3
    4
    # 生成一个行编辑框
    __init__(self, QWidget parent = None)
    # 生成一个带初始值的行编辑框
    __init__(self, QString contents, QWidget parent = None)
  • clear(self):清除编辑框内容;
  • setText(self, QString):设置编辑框的内容;
  • text(self):取编辑框内的文本内容;
  • setMaxLength(self, int):设置编辑框能够输入的最大长度
  • 3、文本编辑框QTextEdit

    1
    2
    # QTextEdit类
    logedit = QtGui.QTextEdit(widget)
  • cursorPositionChanged():光标位置改变触发;
  • textChanged(const QString&):文本内容改变时触发的信号;
  • 构造方法:

    1
    2
    3
    4
    # 生成一个文本编辑框
    __init__(self, QWidget parent = None)
    # 生成一个有初始文本的文本编辑框
    __init__(self, QString_text, QWidget parent = None)
  • clear(self):清除编辑框内容;
  • setText(self, QString):设置编辑框的内容;
  • toPlainText(self):以文本的格式取编辑框内的文本内容;
  • toHtml(self):以HTML的格式取编辑框内的文本内容;
  • 4、标签QLabel

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

    构造方法:

    1
    2
    3
    __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

    1
    2
    # 得到下拉框对象
    select_box= QtGui.QComboBox(widget)
  • currentIndexChanged(int):选择项改变时触发,返回当前选项序号
  • currentIndexChanged(const QString&):选择项改变时触发,返回当前选项文本
  • activated(int):当用户选择下拉列表的项时触发,即使选择项未改变
  • activated(const QString&):当用户选择下拉列表的项时触发,即使选择项未改变
  • 构造方法:

    1
    __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

    1
    2
    # 树结构对象
    casetree = QtGui.QTreeWidget(self.centralwidget)
  • itemClicked(QTreeWidgetItem*,int):选项被点击时触发
  • itemCollapsed(QTreeWidgetItem*):子选项被隐藏时触发
  • itemDoubleClicked(QTreeWidgetItem*,int):选项被双击时触发
  • itemExpanded(QTreeWidgetItem*):子选项被展示时触发
  • 构造方法:

    1
    __init__(self, QWidget parent = None)
  • setColumnCount(self, int columns):设置树结构的列数;
  • setHeaderLabels(self, QStringList labels):设置列标签;
  • headerItem(self):返回用于树窗口小部件标题的项目;
  • 7、树目录QTreeWidgetItem

    1
    root= QtGui.QTreeWidgetItem(self.casetree)

    构造方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    __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)指定每个组件(控件)的大小和位置。

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

    2、框布局

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    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):给布局添加另一个布局,使用框布局通常需要用该方法将水平布局和垂直布局结合;
  • 代码实例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    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界面,学习常用的几个类。

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    #!/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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    # -*- 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类型的窗口都不能这样使用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    # -*- 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)包括鼠标点击、键盘按键输入等事件。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    #!/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()方法连接信号与槽函数。此方法一般传入的参数为发送信号的对象、信号、对信号作出反应的方法(槽函数)。

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    # -*- 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线程与逻辑线程之间的数据传递。

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    # -*- 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源码。

    1
    pyuic4 gui.ui > gui.py

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

    Designer工具

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

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

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

  • 对象查看器:查看当前页面上存在的对象以及层次结构,显示对象名与对象类型,我们可以在这里修改对象名;
  • 属性编辑器:用于编辑对象的属性信息,在页面或对象查看器上选择对象,然后在属性编辑器上就能查看或修改到该对象所拥有的属性;
  • 资源浏览器:查看可用资源;
  • 信号/槽编辑器:创建信号与槽的关系,可以指定到某个对象
  • 动作编辑器:编辑动作,可添加到菜单栏或工具栏
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    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类有哪些方法。

  • finished() 当线程执行完成触发该信号
  • started() 当线程开始时触发该信号
  • terminated() 当线程被中断停止时触发该信号
  • __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方法。

    代码实例如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    # -*- 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. 画图得到gui.ui文件,通过命令转换为python源码
    2. 编写主界面源码,得到界面
    3. 定义config.ini文件用来保存GUI界面的参数信息
    4. 编写后端代码(线程类)
    5. 连接信号和槽函数
    6. 安装PyQt时,注意版本之间的对应关系(包括位版本,如32位、64位)。

    7. 编写线程代码时,注意线程卡死问题。

    8. GUI界面参数传递到后台,注意参数的类型和值。一般的,都需要对参数进行处理。

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