当前位置:   article > 正文

第十九章 GUI 库:PyQt5_pyqt5库

pyqt5库

 
PyQt是另外一套基于Python的GUI框架,目前最新版本是5,所以习惯上称为PyQt5。PyQt5 的功能要远比tkinter框架强大得多。其实PyQt只是用Python语言对QT做了一个封装,底层仍然是使用C++编写的QT核心图形库,所以PyQt在运行效率上非常高,编写的GUI程序与本地应用是完全一样的。标准的QT开发使用的是C++语言,开发效率比较低,而使用Python 语言进行封装后,开发效率也大大提升了,因此,PyQt 在开发效率和运行效率上都有一个非常好的表现,而且还可以进行可视化开发。

官方参考:https://www.riverbankcomputing.com/static/Docs/PyQt5/sip-classes.html

19.1 PyQt5 简介

PyQt是英国的Riverbank Computing公司开发的一套封装QT程序库的Python GUI库,由一系列Python模块组成。包含了超过620个类6000个函数和方法,能在很多流行的操作系统(UNIX、Linux、Windows、Mac OS等)上运行。

PyQt5 类分为很多模块,主要模块有:

  • QtCore: 包含了核心的非GUI的功能。这些功能主要与时间、文件、文件夹、各种数据、流、URLs、mime类文件、进程和线程有关。

  • QtGui: 包含了窗口系统、事件处理、2D图像、基本绘画、字体和文字类。

  • QtWidgets: 包含了一系列创建桌面应用的UI元素。

  • QtMultimedia: 包含了处理多媒体的内容和调用摄像头API的类。

  • QtBluetooth: 包含了查找和连接蓝牙的类。

  • QtNetwork: 包含了网络编程的类,这些工具能让TCP/IP和UDP开发变得更加方便和可靠。

  • QtPositioning: 包含了定位的类,可以使用卫星、WiFi等进行定位。

  • QtWebSockets: 包含了WebSocket 协议的类。

  • QtWebKit: 包含了一个基于WebKit2的Web浏览器。

  • QtWebKitWidgets: 包含了基于QtWidgets的WebKit1的类。

  • QtXml: 包含了处理XML的类,提供了SAX和DOMAPI的工具。

  • QtSvg: 提供了显示SVG内容的类,Scalable Vector Graphics (SVG)是一种基于可扩展标记语言(XML),用于描述二维矢量图形的图形格式。

  • QtSql: 提供了处理数据库的工具。

  • QtTest: 提供了测试PyQt5应用的工具。

19.2 安装 PyQt5

在使用PyQt5开发GUI程序之前,首先要安装PyQt5。包括PyQt5的运行环境,以及用于可视化开发的QTDesigner,用于将.ui文件转换为Python代码的PyUIC。

19.2.1 PyQt5 开发环境搭建

方式一

1.下载PyQt5的源代码:
https://www.riverbankcomputing.com/software/pyqt/download5

2.下载完PyQt5的源代码后,按如下页面的说明配置和编译PyQt5的源代码:
http://pyqt.sourceforge.net/Docs/PyQt5/installation.html#downloading- pyqt5

方式二

1.安装PyQt5的命令行如下:

pip install pyqt5
  • 1

要注意的是,执行这行命令不光是安装PyQt5本身,还会安装很多依赖库,所以要保证稳定而快速的网络连接。

2.如果要卸载PyQt5,可以使用下面的命令行。

pip uninstall pyqt5
  • 1

安装完后,运行python命令,进入Python的REPL环境,输入import PyQt5,按Enter 键后,如果没有抛出异常,说明PyQt5已经安装成功。

19.2.2 配置 QTDesigner(可视化开发)

QTDesigner是用于可视化开发的工具,在QT安装包中,在使用QTDesigner之前,先要安装QT。可以从下面的页面下载QT的在线安装版本(请选择开源版本):

https://www.qt.io/download
  • 1

如果不想在线安装,可以到下面的页面下载QT的离线安装包,请选择相应的操作系统版本:

https://download.qt.io/archive/qt/5.10/5.10.0
  • 1

QT安装非常简单,直接单击安装程序并按提示操作即可。

如果使用的是Anaconda Python 开发环境,那就不需要安装QT,因为Anaconda 中已经集成了QTDesigner。得到QTDesigner后,可以选择一个Python IDE,将QTDesigner与这个IDE关联,也就是在IDE中可以调用QTDesigner。

选择PyCharm作为与QTDesigner关联的IDE,现在要将QTDesigner添加到PyCharm的扩展工具中。首先打开PyCharm的Preferences窗口(Windows版的PyCharm需要选择File→Settings菜单项打开Settings窗口),然后在左侧找到External Tools 节点,在右侧会显示当前所有的扩展工具,默认是空。单击下方的加号按钮添加一个扩展工具,这时会弹出一个Create Tool 对话框,然后将内容填写到相应的文本框中。

Create Tool对话框中需要填写的内容包括Name、Description(可选)、Program和Working directory四项。其中,Program要填写QTDesigner 的路径。这是一个可执行程序,如果是Windows,是一个designer.exe文件。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
然后按Ctrl+S键保存窗口,会将窗口保存成一个扩展名为 .ui 的文件,这就是窗口布局文件。

19.2.3 配置 PyUIC

在上边已经将设计好的窗口保存成 .ui 文件了,但这个.ui 文件并不能被Python直接使用,需要用工具将这个 .ui 文件转换为Python源代码文件(.py 文件),这个工具就是PyUIC。
在这里插入图片描述
在这里插入图片描述
test03|.py文件中只包含一个名为Ui__MainWindow的类,在这个类的setupUi方法中创建了所有的控件,不过这个类还不能直接运行,需要在test.py文件中输入如下代码才能启动程序。

# test.py
import sys
# 等价于调用test03脚本
import test03
from PyQt5.QtWidgets import QApplication,QMainWindow

if __name__ == '__main__':
	app = QApplication(sys.argv)
	MainWindow = QMainWindow()
	ui = test03.Ui_MainWindow ()
	# 调用setupUi方法动态创建控件
	ui.setupUi(MainWindow)
	# 显示窗口
	MainWindow.show()
	# 当窗口关闭后会退出程序
	sys.exit(app.exec_())
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

在这里插入图片描述

19.3 编写第一个 PyQt5 程序

本节主要采用手工编写代码的方式学习PyQt5。当然,如果对这些技术已经比较精通,可以直接使用QTDesigner来设计UI。

编写一个PyQt5程序必须使用两个类: QApplicationQWidget。这两个类都在 PyQt5.QtWidgets 模块中,所以首先要导入这个模块。

QApplication类的实例表示整个应用程序。该类的构造方法需要传入Python程序的命令行参数(需要导入sys模块),因此,基于PyQt5的程序也能在终端中执行,并传入命令行参数。

QWidget类的实例相当于一个窗口,所有的控件都可以放到这个窗口上。可以通过QWidget实例中的方法控制这个窗口,例如,通过resize 方法改变窗口的尺寸,通过move方法移动窗口,通过setWindowTitle方法设置窗口的标题。最后,还需要调用show 方法显示窗口。要注意的是,调用show方法显示窗口后,程序并不会处于阻塞状态,会继续往下执行,通常需要在程序的最后调用app.exec_方法进入程序的主循环,在主循环中会不断检测窗口中发生的事件,如单击按钮事件,当窗口关闭后,主循环就会结束,一般会通过sys.exit函数确保主循环安全结束。

import sys
# 导入 QApplication, QWidget 类
from PyQt5.QtWidgets import QApplication, QWidget
if __name__ == '__main__':
    # 创建 QApplication 类的实例,并传入命令行参数
    app = QApplication(sys.argv)
    # 创建 QWidget 类的实例,相当于创建一个窗口
    w = QWidget()
    # 设置窗口的宽、高
    w.resize(400, 250)
    # 移动窗口
    w.move(300, 300)
    # 设置窗口的标题
    w.setWindowTitle('第一个PyQt5应用')
    # 显示窗口
    w.show()
    # 进入程序主循环,并通过 exit 确保主循环安全结束
    sys.exit(app.exec_())
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

在这里插入图片描述

19.4 窗口的基本功能

19.4.1 设置窗口图标

设置窗口图标需要使用setWindowlcon 方法,不过QApplication 类和QWidget 类都有setWindowlcon方法,那么到底使用哪一个setWindowlcon方法呢?

对于Windows系统来说,使用哪一个setWindowlcon方法都一样,都会在窗口的左上角显示图标,但在Mac OS X下,使用QWidget 类的setWindowlcon 方法不会在窗口上显示图标,只有调用QApplication类的setWindowlcon方法才会在窗口上显示图标。setWindowlcon 方法需要传入一个图像文件路径,文件格式可以使用png、jpg等。建议使用png格式,因为png格式支持透明背景。

import sys
from PyQt5.QtWidgets import QApplication, QWidget
# 导入 QIcon ,用于装载图像文件
from PyQt5.QtGui import QIcon
if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = QWidget()
    # 设置窗口宽高、位置
    w.setGeometry(400, 250, 300, 200)
    w.setWindowTitle('窗口图标')
    # 设置窗口图标
    app.setWindowIcon(QIcon('python.png'))
    w.show()
    sys.exit(app.exec_())
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

在这里插入图片描述

19.4.2 显示提示框

提示框就是一个无法获得焦点的窗口。通常用提示框作为实时帮助或提示使用。例如,当鼠标放在一个按钮上,就会显示这个按钮的作用和使用方法。

提示框需要使用QWidget类的setToolTip方法创建。任何可视化控件类都有这个方法,因为可视化控件类是从QWidget类派生的。setToolTip接收一个字符串类型的参数值,作为提示框显示的文本。并不是创建了提示框就会立刻显示,需要将鼠标放在添加了提示框的窗口或控件上,大概1s,就会显示相应的提示框,如果鼠标不动,提示框会在数秒后自动关闭,如果鼠标移动,提示框会立刻关闭。

import sys
from PyQt5.QtWidgets import (QWidget, QToolTip,
                             QPushButton, QApplication)
# 导入 QFont 类用于设置字体和字号
from PyQt5.QtGui import QFont

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = QWidget()
    w.setGeometry(400, 300, 300, 220)
    w.setWindowTitle('提示框')
    # 设置提示框中的字体和字号
    QToolTip.setFont(QFont('SansSerif', 20))
    # 为窗口设置提示框--好像不显示,待确定
    w.setToolTip('这是一个窗口\n设计者:涛哥')
    # 设置一个按钮,将按钮显示在窗口上
    btn = QPushButton('Button', w)
    # 为按钮设置提示框
    btn.setToolTip('这是一个按钮\n设计者:taoge')
    btn.resize(btn.sizeHint())
    btn.move(50, 50)
    w.show()
    sys.exit(app.exec_())
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

在这里插入图片描述

19.4.3 关闭窗口

关闭窗口可以直接使用系统内置的quit方法,如果单击按钮关闭窗口,可以直接将按钮的单击事件与quit 绑定。

import sys
from PyQt5.QtWidgets import QWidget, QPushButton, QApplication
from PyQt5.QtCore import QCoreApplication

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = QWidget()
    w.setGeometry(300, 300, 300, 220)
    w.setWindowTitle('关闭窗口')
    qbtn = QPushButton('Quit', w)
    # 将按钮的单击事件与quit绑定
    qbtn.clicked.connect(QCoreApplication.instance().quit)
    qbtn.resize(qbtn.sizeHint())
    qbtn.move(50, 50)
    w.show()
    sys.exit(app.exec_())	
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

在这里插入图片描述

19.4.4 消息盒子

消息盒子 ( MessageBox) 其实就是各种类型的消息对话框,如信息对话框、警告对话框、询问对话框等。这些对话框的区别主要是对话框的图标以及按钮的个数。QMessageBox类提供了若干个静态方法可以显示各种类型的对话框。例如,information 方法用于显示信息对话框,warning 方法用于显示警告对话框,question 方法用于显示询问对话框。

import sys
from PyQt5.QtWidgets import QWidget, QMessageBox, QApplication


# 封装窗口代码类
class MessageBox(QWidget):

    def __init__(self):
        super().__init__()
        # 初始化窗口
        self.initUI()

    def initUI(self):
        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('消息盒子')
        # 显示窗口
        self.show()

    # 窗口的关闭事件
    def closeEvent(self, event):
        # 显示询问对话框
        reply = QMessageBox.question(self, '消息',
									 "你真的要退出吗?", QMessageBox.Yes |
									 QMessageBox.No, QMessageBox.No)

        if reply == QMessageBox.Yes:
            # 调用event的accept方法才会真正关闭窗口
            event.accept()
        else:
            # 调用event的ignore方法会取消窗口的关闭动作
            event.ignore()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    # 创建MessageBox类的实例,在该类的构造方法中通过initUI方法初始化窗口,以及显示窗口
    ex = MessageBox()
    sys.exit(app.exec_())
  • 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

在这里插入图片描述

  • 本例采用了面向对象的方式将与窗口相关的代码都封装在了MessageBox类中,这是编写PyQt5程序的常用方式,以后编写的代码都会采用这种方式。
  • closeEvent 方法是窗口的关闭事件方法,当窗口关闭时,会首先调用该方法。这个方法的调用是自动的,不需要干预,也不需要注册该方法。方法名字必须叫closeEvent。
  • closeEvent方法的第2个参数是与关闭事件有关的对象。其中accept方法会让窗口关闭,ignore方法会取消窗口关闭动作。如果这两个方法都不调用,那么窗口仍然会关闭。

19.4.5 窗口居中

窗口对象(QWidget)并没有直接提供让窗口居中的方法,不过可以曲线救国,根据窗口的宽度、高度以及屏幕的宽度和高度,计算出窗口左上角的坐标,然后使用窗口对象的move方法将窗口移动到中心的位置。

import sys
from PyQt5.QtWidgets import QWidget, QDesktopWidget, QApplication


# 在屏幕中心显示窗口类
class CenterWindow(QWidget):

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

        self.initUI()

    def initUI(self):
        self.resize(250, 150)
        # 调用center方法让窗口在屏幕中心显示
        self.center()
        self.setWindowTitle('窗口居中')
        self.show()

    def center(self):
        qr = self.frameGeometry()
        desktop = app.desktop()
        # 计算窗口处理屏幕中心时左上角的坐标,然后将窗口移动到中心位置
        self.move((desktop.width() - self.width()) / 2, (desktop.height() - self.height()) / 2)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = CenterWindow()
    sys.exit(app.exec_())

  • 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

在这里插入图片描述

19.5 布局

在一个GUI程序里,布局是非常重要的。布局的作用是管理应用中的控件在窗口上的摆放位置以及控件自身的尺寸。PyQt5 支持如下三种布局:绝对布局、盒布局、网格布局。

19.5.1 绝对布局

在窗口上是以像素为单位设置尺寸和位置的,所以可以用绝对定位的方式确定控件的尺寸,以及控件在窗口上的位置。

import sys
from PyQt5.QtWidgets import QWidget, QLabel, QApplication

class AbsoluteLayout(QWidget):

    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):

        lbl1 = QLabel('姓名', self)
        # 设置QLabel控件的位置是 15,10
        lbl1.move(15, 10)

        lbl2 = QLabel('年龄', self)
        # 设置QLabel控件的位置是 35,40
        lbl2.move(35, 40)

        lbl3 = QLabel('所在城市', self)
        # 设置QLabel控件的位置是 55,70
        lbl3.move(55, 70)

        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('绝对布局')
        self.show()

if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = AbsoluteLayout()
    sys.exit(app.exec_())
  • 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

在这里插入图片描述

绝对布局尽管非常灵活,可以任意摆放控件的位置,但也有其局限性。

  • 控件的位置固定,不会随着窗口尺寸的变化而变化。例如,当窗口默认尺寸控件在窗口中心时,如果窗口的尺寸改变,那么这个控件将不再处于窗口中心。
  • 无法使用不同平台和不同分辨率的显示器。
  • 更改字体大小可能会破坏布局。
  • 如果决定对应用进行重构,那么还需要重新计算每一个控件的位置和大小。

因此,绝对布局尽管非常灵活,但并不能适用于所有的情况,如果要让布局适应性更强,可以使用盒布局、网格布局。

19.5.2 盒布局

使用盒布局能让程序具有更强的适应性。盒布局分为水平盒布局和垂直盒布局,分别用QHBoxLayout类和QVBoxLayout类表示。水平盒布局是将控件沿水平方向摆放,垂直盒布局是将控件沿垂直方向摆放。

如果要对控件使用盒布局,需要通过盒布局对象的addWidget方法将控件添加到盒布局中,如果要将一个布局添加到盒布局中作为子布局存在,需要通过盒布局对象的addLayout方法将布局对象添加到盒布局中。

import sys
from PyQt5.QtWidgets import (QWidget, QPushButton,
    QHBoxLayout, QVBoxLayout, QApplication)


class BoxLayout(QWidget):

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

        self.initUI()

    def initUI(self):
        # 创建 "确定"、"取消" 按钮
        okButton = QPushButton("确定")
        cancelButton = QPushButton("取消")
        # 创建水平盒布局对象
        hbox = QHBoxLayout()
        # 让两个按钮始终在窗口的右侧
        hbox.addStretch()
        # 将 "确定"、"取消" 按钮添加到水平盒布局中
        hbox.addWidget(okButton)
        hbox.addWidget(cancelButton)
        # 创建垂直盒布局对象
        vbox = QVBoxLayout()
        # 让控件始终在窗口的下方
        vbox.addStretch()
        # 将水平盒布局对象添加到垂直盒布局中
        vbox.addLayout(hbox)
        # 将垂直盒布局应用于当前窗口
        self.setLayout(vbox)

        self.setGeometry(300, 300, 300, 150)
        self.setWindowTitle('盒布局')
        self.show()

if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = BoxLayout()
    sys.exit(app.exec_())
  • 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

在这里插入图片描述

19.5.3 网络布局

网格布局相当于一个二维表,将窗口划分为若干个行若干个列。一个控件可以摆放在一个单元格中,也可以横跨多行多列。网格布局用QGridLayout类表示。该类中常用的方法是addWidget,可以将一个控件添加到网格布局中,并指定该控件从第几行第几列开始,以及占用几行几列。还可以使用addSpacing方法指定在水平和垂直方向单元格之间的距离。

import sys
from PyQt5.QtWidgets import (QWidget, QLabel, QLineEdit, QTextEdit, QGridLayout, QApplication)

class FormGridLayout(QWidget):

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

        self.initUI()


    def initUI(self):

        title = QLabel('标题')
        author = QLabel('作者')
        summary = QLabel('摘要')

        titleEdit = QLineEdit()
        authorEdit = QLineEdit()
        summaryEdit = QTextEdit()
        # 创建网络布局对象
        grid = QGridLayout()
        # 设置单元格之间的距离
        grid.setSpacing(10)
        # 向网路布局添加title控件,位于第2行第1列
        grid.addWidget(title, 1, 0)
        # 向网路布局添加titleEdit控件,位于第2行第2列
        grid.addWidget(titleEdit, 1, 1)
        # 向网路布局添加author控件,位于第3行第1列
        grid.addWidget(author, 2, 0)
        # 向网路布局添加authorEdit控件,位于第3行第2列
        grid.addWidget(authorEdit, 2, 1)
        # 向网路布局添加summary控件,位于第4行第1列
        grid.addWidget(summary, 3, 0)
        # 向网路布局添加summaryEdit控件,位于第4行第2列,并且占用了5行1列
        grid.addWidget(summaryEdit, 3, 1, 5, 1)
        # 将网络布局应用于当前窗口
        self.setLayout(grid)

        self.setGeometry(300, 300, 350, 300)
        self.setWindowTitle('网格布局')
        self.show()


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = FormGridLayout()
    sys.exit(app.exec_())
	
  • 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

在这里插入图片描述
当改变窗口尺寸时,最下方的文本输入框会随着窗口尺寸的变化在垂直和水平方向进行缩放。而前两个文本输入框只会随着窗口尺寸的变化在水平方向上缩放,因为QLineEdit是单行输入控件,而QTextEdit是多行输入控件。

19.6 控件

控件是开发GUI程序必不可少的组成部分。就像盖房子的砖和瓦一样,需要用一砖一瓦盖起高楼大厦。PyQt5 中的控件很多,本节介绍常用的几种控件,包括QPushButton (按钮控件)、QLineEdit ( 单行文本编辑控件)、QCheckBox (复选框控件)、QSlider (滑块控件)、QProgressBar (进度条控件)、QPixmap (图像控件)、QComboBox (下拉列表框控件) 和QCalendarWidget (日历控件)。

19.6.1 QPushButton 控件

QPushButton是一个按钮控件,不过这个按钮控件支持两种状态,一种是Normal状态,另外一种是Checked状态。Normal状态就是正常的未按下的状态,而Checked状态就是按钮被按下的状态,按下后颜色变为蓝色,表示已经被选中。

from PyQt5.QtWidgets import (QWidget, QPushButton, QFrame, QApplication)
# 导入用于设置颜色的QColor类  
from PyQt5.QtGui import QColor
import sys


class PushButton(QWidget):

    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        # 创建 QColor 对象,初始颜色为黑色
        self.color = QColor(0, 0, 0)
        # 创建红色的QPushButton对象
        redButton = QPushButton('红', self)
        # 必须用setCheckable(True)才能让按钮可以设置两种状态
        redButton.setCheckable(True)
        redButton.move(10, 10)
        # 将setColor方法与按钮的单击事件关联,bool是一个类,表示setColor参数类型是一个布尔类型
        # 这个布尔类型的参数值表示按钮 按下和抬起两种状态
        redButton.clicked[bool].connect(self.setColor)

        # 创建绿色的QPushButton对象
        greenButton = QPushButton('绿', self)
        greenButton.setCheckable(True)
        greenButton.move(10, 60)
        greenButton.clicked[bool].connect(self.setColor)

        # 创建蓝色的QPushButton对象
        blueButton = QPushButton('蓝', self)
        blueButton.setCheckable(True)
        blueButton.move(10, 110)
        blueButton.clicked[bool].connect(self.setColor)

        # 创建用于显示当前颜色的QFrame对象
        self.square = QFrame(self)
        self.square.setGeometry(150, 20, 100, 100)
        # 设置QFrame的背景色
        self.square.setStyleSheet("QWidget { background-color: %s }" % self.color.name())

        self.setGeometry(300, 300, 280, 170)
        self.setWindowTitle('按钮控件')
        self.show()

    # 按钮的单击事件方法,3个按钮共享着一个方法
    def setColor(self, pressed):
        # 获取单击了哪一个按钮
        source = self.sender()

        if pressed:
            val = 255
        else:
            val = 0
        # 红色按下,设置颜色为红色
        if source.text() == "红":
            self.color.setRed(val)
        # 绿色按下,设置颜色为绿色
        elif source.text() == "绿":
            self.color.setGreen(val)
        # 蓝色按下,设置颜色为蓝色
        else:
            self.color.setBlue(val)
        # 用设置后的颜色改变QFrame的背景色
        self.square.setStyleSheet("QFrame { background-color: %s }" % self.color.name())

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = PushButton()
    sys.exit(app.exec_())
  • 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

在这里插入图片描述

19.6.2 QLineEdit 控件

QLineEdit是用于输入单行文本的控件,以前多次使用过这个控件。

import sys
from PyQt5.QtWidgets import (QWidget, QLabel, QLineEdit, QApplication)

class LineEdit(QWidget):

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

        self.initUI()

    def initUI(self):
        # 创建QLabel对象
        self.label = QLabel(self)
        # 创建QLineEdit对象
        lineEdit = QLineEdit(self)
        lineEdit.move(80, 100)
        self.label.move(80, 40)
        # 将onChanged方法与QLineEdit控件的文本变化事件绑定,需要传入onChanged方法一个字符串类型的参数,str表示字符串,str是一个类
        lineEdit.textChanged[str].connect(self.onChanged)

        self.setGeometry(300, 300, 280, 170)
        self.setWindowTitle('QLineEdit控件')
        self.show()

    # 文本变化时调用的方法,text参数表示变化后的文本
    def onChanged(self, text):
        self.label.setText(text)
        self.label.adjustSize()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = LineEdit()
    sys.exit(app.exec_())
  • 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

在这里插入图片描述

19.6.3 QCheckBox 控件

QCheckBox是复选框控件,用于进行二值选择。也可以多个QCheckBox 控件在一起使用,用于对多个设置项进行多选操作。QCheckBox 控件默认的是未选中状态,调用 QCheckBox 对象的toggle方法可以让QCheckBox控件处于选中状态.QCheckBox控件常用的事件是stateChanged,当QCheckBox控件选中状态发生变化时会触发该事件。

from PyQt5.QtWidgets import QWidget, QCheckBox, QApplication
from PyQt5.QtCore import Qt
import sys

class CheckBox(QWidget):

    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        # 创建QCheckBox对象
        cb = QCheckBox('请选择我', self)
        cb.move(20, 20)
        # 调用这个方法会让QCheckBox控件处于选中状态
        # cb.toggle()
        # 将changeTitle方法与QCheckBox控件的stateChange事件绑定
        cb.stateChanged.connect(self.changeTitle)

        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('还没有选择我')
        self.show()

    def changeTitle(self, state):
        # Qt.Checked 是一个变量,表示选中状态
        if state == Qt.Checked:
            self.setWindowTitle('已经选择我了')
        else:
            self.setWindowTitle('还没有选择我')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = CheckBox()
    sys.exit(app.exec_())
  • 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

在这里插入图片描述

19.6.4 QSlider 控件

QSlider是滑块控件,用于控制值在一定的范围变化。可以将QSlider控件的valueChanged事件与一个方法绑定,用来监听滑块移动的动作。还可以使用setMinimum方法和setMaximum方法设置滑块可以变化的最小值和最大值。

from PyQt5.QtWidgets import (QWidget, QSlider, QLabel, QApplication)
from PyQt5.QtCore import Qt

import sys

class Slider(QWidget):
    
    def __init__(self):
        super().__init__()
        
        self.initUI()
        
        
    def initUI(self):      
        # 创建QSlider对象
        sld = QSlider(Qt.Horizontal, self) 
        # 设置滑块最小值和最大值
        sld.setMinimum(10) 
        sld.setMaximum(500)     
        sld.setGeometry(30, 40, 100, 30)
        # 将changeValue方法与QSlider控件的valueChanged事件绑定
        sld.valueChanged[int].connect(self.changeValue)
        # 创建QLabel对象,用于显示滑块的当前值
        self.label = QLabel(self)      
        self.label.setGeometry(160, 40, 80, 30)
        
        self.setGeometry(300, 300, 280, 170)
        self.setWindowTitle('QSlider控件')
        self.show()
                
    def changeValue(self, value):
        # 在QLabel控件上显示滑块的当前值
        self.label.setText(str(value))
       
            
if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Slider()
    sys.exit(app.exec_())
  • 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

在这里插入图片描述

19.6.5 QProgressBar 控件

QProgressBar是进度条控件,效果与QSlider 控件类似,只是没有滑块,要想改变QProgressBar控件的当前值,需要通过QProgressBar控件的setValue方法设置。QProgressBar控件默认最小值是0,默认最大值是100,可以通过setMinimum方法和setMaximum方法设置最小值和最大值,也可以通过minimum方法和maximum方法获得最小值和最大值。

from PyQt5.QtWidgets import (QWidget, QProgressBar,
                             QPushButton, QApplication)
from PyQt5.QtCore import QBasicTimer
import sys


class ProgressBar(QWidget):

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

        self.initUI()

    def initUI(self):

        self.pbar = QProgressBar(self)
        self.pbar.setGeometry(40, 40, 200, 25)
        # 创建QPushButton对象
        self.btn = QPushButton('开始', self)
        self.btn.move(40, 80)
        # 将按钮的单击事件与doAction方法关联
        self.btn.clicked.connect(self.doAction)
        # 创建定时器对象
        self.timer = QBasicTimer()
        # QBasicTimer控件的当前值
        self.value = 0
        self.setGeometry(300, 300, 280, 170)
        self.setWindowTitle('QProgressBar控件')
        self.show()

    # 定时器调用的方法,必须命名为timerEvent
    def timerEvent(self, e):
        # 当self.value >= 100表示任务完成,停止定时器
        if self.value >= 100:
            self.timer.stop()
            self.btn.setText('完成')
            return
        # 每次QProgressBar控件的当前值加1
        self.value = self.value + 1
        # 更新QProgressBar控件的当前值
        self.pbar.setValue(self.value)

    # 按钮的单击事件方法
    def doAction(self):
        # 如果定时器处于活跃状态,停止定时器
        if self.timer.isActive():
            self.timer.stop()
            self.btn.setText('开始')
        else:
            # 如果定时器还没有开始,启动定时器,时间间隔是100ms
            self.timer.start(100, self)
            self.btn.setText('停止')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = ProgressBar()
    sys.exit(app.exec_())
  • 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

在这里插入图片描述

19.6.6 QPixmap 控件

QPixmap是用于显示图像的控件,通过QPixmap类的构造方法可以指定要显示的图像文件名。

from PyQt5.QtWidgets import (QWidget, QHBoxLayout, QLabel, QApplication)
from PyQt5.QtGui import QPixmap
import sys


class Pixmap(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        hbox = QHBoxLayout(self)
        # 创建QPixmap对象,并指定要显示的图像文件
        pixmap = QPixmap("ha.JPG")

        lbl = QLabel(self)
        lbl.setPixmap(pixmap)

        hbox.addWidget(lbl)
        self.setLayout(hbox)
        self.move(300, 200)
        self.setWindowTitle('显示图像(QPixmap控件)')
        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Pixmap()
    sys.exit(app.exec_())
  • 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

在这里插入图片描述

19.6.7 QComboBox 控件

QComboBox是下拉列表控件,允许在列表中显示多个值,并且选择其中一个。可以使用QComboBox对象的addItem方法添加列表项,并通过QComboBox控件的activated事件处理选择列表项的动作。

from PyQt5.QtWidgets import (QWidget, QLabel, QComboBox, QApplication)
import sys


class ComboBox(QWidget):

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

        self.initUI()

    def initUI(self):
        self.lbl = QLabel("中国", self)
        self.lbl.move(50, 150)
        # 向第1个QComboBox控件添加若干个列表项
        combo = QComboBox(self)
        combo.addItem("中国")
        combo.addItem("美国")
        combo.addItem("法国")
        combo.addItem("德国")
        combo.addItem("俄罗斯")
        combo.addItem("澳大利亚")
        combo.move(50, 50)
        self.lbl.move(50, 150)
        # 将onActivated方法与activated事件绑定
        combo.activated[str].connect(self.onActivated)

        combo1 = QComboBox(self)
        # 向第2个QComboBox控件添加若干个列表项
        combo1.addItem("Item1")
        combo1.addItem("Item2")
        combo1.addItem("Item3")
        combo1.move(200, 50)

        self.setGeometry(300, 300, 300, 200)
        self.setWindowTitle('QComboBox控件')
        self.show()

    def onActivated(self, text):
        # 当选择第1个QComboBox控件的列表后,将列表项的文本显示在QLabel控件中
        self.lbl.setText(text)
        self.lbl.adjustSize()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = ComboBox()
    sys.exit(app.exec_())
  • 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

在这里插入图片描述

19.6.8 QCalendarWidget 控件

QCalendarWidget是用于显示日历的控件,可以按年、月显示日历,通过setGridVisible方法可以设置是否在日期中显示网格,通过绑定clicked事件,可以处理单击日历某一天的动作。

from PyQt5.QtWidgets import (QWidget, QCalendarWidget, QLabel, QApplication, QVBoxLayout)
from PyQt5.QtCore import QDate
import sys


class CalendarWidget(QWidget):

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

        self.initUI()

    def initUI(self):
        vbox = QVBoxLayout(self)

        cal = QCalendarWidget(self)
        # 让日历控件显示网格
        cal.setGridVisible(True)
        # 将showDate方法与clicked事件绑定
        cal.clicked[QDate].connect(self.showDate)
        vbox.addWidget(cal)
        self.lbl = QLabel(self)
        # 获取当前选择的日期
        date = cal.selectedDate()
        self.lbl.setText(date.toString())
        vbox.addWidget(self.lbl)
        self.setLayout(vbox)
        self.setGeometry(300, 300, 350, 300)
        self.setWindowTitle('Calendar控件')
        self.show()

    def showDate(self, date):
        # 选择某个日期后,会在QLabel控件中显示详细的时间
        self.lbl.setText(date.toString())


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = CalendarWidget()
    sys.exit(app.exec_())
  • 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

在这里插入图片描述

19.7 菜单

调用QMainWindow类的menuBar方法可以获得主窗口的QMenuBar对象,该对象表示主窗口的菜单栏,通过QMenuBar对象的addMenu方法可以在菜单栏中添加菜单项,然后通过addAction方法添加子菜单项。

import sys
from PyQt5.QtWidgets import QMainWindow, QAction, QMenu, QApplication


class Menu(QMainWindow):

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

        self.initUI()

    def initUI(self):
        menubar = self.menuBar()
        print(menubar)
        # 添加菜单 或 子菜单
        fileMenu = menubar.addMenu('文件')
        newAct = QAction('新建', self)
        impMenu = QMenu('导入', self)
        impAct1 = QAction('从PDF导入', self)
        impAct2 = QAction('从Word导入', self)
        # 为菜单添加单击处理事件
        impAct1.triggered.connect(self.actionHandler1)
        impAct2.triggered.connect(self.actionHandler2)
        # 下面的代码将前边建立的操大项关联起来
        impMenu.addAction(impAct1)
        impMenu.addAction(impAct2)

        fileMenu.addAction(newAct)
        fileMenu.addMenu(impMenu)

        self.setGeometry(300, 300, 300, 200)
        self.setWindowTitle('菜单')
        self.show()

    # 响应菜单项的事件方法
    def actionHandler1(self):
        print('从PDF导入')

    def actionHandler2(self):
        print('从Word导入')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Menu()
    sys.exit(app.exec_())
  • 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

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/138729?site
推荐阅读
相关标签
  

闽ICP备14008679号