暑期学什么?——关于Pyqt5

目录

前言

一、PyQt是什么?

二、Python GUI开发热门选择

三、PyQt5安装

(一)使用命令

(二)使用图形化

四、基本UI界面设计

(一)、创建第一个Pyqt程序

(二)、创建带有按钮的窗口

(三)、创建带有文本显示的窗口

(四)、创建带有输入框的窗口

(五)、创建可以调整窗口大小的窗口

(六)、创建在屏幕中间的窗口

(七)、创建显示ICON图片的窗口

五、Pyqt5的使用介绍

(一)、PyQt5布局管理:

1.QBoxLayout

运行效果:

2.QGridLayout

2-1:QGridLayout简单介绍

2-2:QGridLayout案例分析(简单计算器实现)

3.QFormLayout

4.QStackedLayout

(二)、窗口分类

1.QWidget

2.QMainWindow

3.QDialog

(三)、信号与槽

1.说明

2.信号

3.槽

4.将信号和槽链接

5.案例

1-功能:接收信号

运行效果:​编辑

2-自定义信号

运行效果:

3-思考与实操

运行效果:

(四)、QT Designer介绍

1.新建主窗口 

​编辑

2.主要功能区域介绍 

      (1)  Widget Box(控件工具箱)

1.显示控件(Display widgets):

​编辑

2.输入控件(Input widgets):提供与用户输入交互

3.按钮控件(Buttons) :供用户选择与执行

4.Containers

5.Item widgets

6.Spacers——Layouts

(2) 设计窗口

(3)菜单栏

(4)工具栏

3.pyqt5工具包介绍

4.将.ui文件转换为.py文件

(1)通过打开Tools->External Tools->PyUIC将.ui文件转换为.py文件。 

(2)通过命令行把.ui文件转换为.py文件 

(3)将资源文件转换成.py文件

6.动态加载ui文件

6-1:动态ui文件的使用

6-2:进阶案例

(五)、多线程介绍

1.引入

运行效果:​编辑

2.pyqt使用线程

(六)、程序打包

1.使用pyinstall

关于这个打包软件这里推荐一个博客大家可以一起学习:

六、其他

(一)补充

(二)使用QT Designer制作网络摄像头监控界面

1.功能需求

(1)监控界面设计

(2)温湿度数据采集

2.软件、硬件、云平台介绍

(1)软件介绍

(2)硬件介绍

(3)云平台介绍

3.软件搭建

4.云平台调试

(三)案例

1.功能需求

(1)界面设计

(2)数据采集

2.软件、硬件、云平台介绍

(1)软件介绍

(2)硬件介绍

(3)云平台介绍

3.软件搭建

4.云平台调试

总结


前言

根据前期的学习完成了pycharm的安装和激活,接下来我们将学习使用python的相关库来完成界面的设计。

一、PyQt是什么?

PyQt的开发者是英国的“Riverbank Computing”公司。它提供了GPL(简单的说,以GPL协议发布到网上的素材,你可以使用,也可以更改,但是经过你更改然后再次发布的素材必须也遵守GPL协议,主要要求是必须开源,而且不能删减原作者的声明信息等)与商业协议两种授权方式,因此它可以免费地用于自由软件的开发。

PyQt可以运行于Microsoft Windows、Mac OS X、Linux以及Unix的多数变种上

PyQt是Python语言的GUI(Graphical User Interface,简称 GUI,又称图形用户接口)编程解决方案之一

可以用来代替Python内置的Tkinter。其它替代者还有PyGTKwxPython等,与Qt一样,PyQt是一个自由软件

文档相关地址:Riverbank Computing | Introduction

二、Python GUI开发热门选择

  • Tkinter

    Python官方采用的标准库,优点是作为Python标准库、稳定、发布程序较小,缺点是控件相对较少。

  • wxPython

    基于wxWidgets的Python库,优点是控件比较丰富,缺点是稳定性相对差点、文档少、用户少。

  • PySide2、PyQt5

    基于Qt 的Python库,优点是控件比较丰富、跨平台体验好、文档完善、用户多。

    缺点是 库比较大,发布出来的程序比较大。

    PyQt5 的开发者是英国的“Riverbank Computing”公司 , 而 PySide2 则是 qt 针对python语言提供的专门

三、PyQt5安装

(一)使用命令

pip install pyqt5 -i https://pypi.tuna.tsinghua.edu.cn/simple

阿里云  https://mirrors.aliyun.com/pypi/simple/

中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/

豆瓣(douban) https://pypi.douban.com/simple/

清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/

中国科学技术大学 https://pypi.mirrors.ustc.edu.cn/simple/

(二)使用图形化


四、基本UI界面设计

(一)、创建第一个Pyqt程序

import sys

from PyQt5.QtWidgets import QApplication, QWidget

if __name__ == '__main__':
    app = QApplication(sys.argv)
#1.只要是QT制作APP,必须有且只有一个 QApplication
#2.sys.argv当做参数的目的是将运行时的命令参数传递给QApplication

    w = QWidget()
    # 设置窗口标题
    w.setWindowTitle("第一个PyQt")
#创建一个QWidget对象,将他的标题设置为"第一个PyQt"
    # 展示窗口
    w.show()
#调用show方法显示出来

    # 程序进行循环等待状态
    app.exec()
#程序开始运行直到关闭窗口


(二)、创建带有按钮的窗口

import sys

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton

if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = QWidget()

    # 设置窗口标题
    w.setWindowTitle("第一个PyQt程序")

    # 在窗口里面添加控件
    btn = QPushButton("按钮")

    # 设置按钮的父亲是当前窗口,等于是添加到窗口中显示
    btn.setParent(w)

    # 展示窗口
    w.show()

    # 程序进行循环等待状态
    app.exec()


(三)、创建带有文本显示的窗口

import sys

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

if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = QWidget()

    # 设置窗口标题
    w.setWindowTitle("第一个PyQt")

    # # 下面创建一个Label,然后调用方法指定父类
    # label = QLabel("账号: ", w)
    # # 设置父对象
    # label.setParent(w)

    # 下面创建一个Label(纯文本),在创建的时候指定了父对象
    label = QLabel("账号: ", w)

    # 显示位置与大小 : x, y , w, h
    label.setGeometry(20, 20, 30, 30)

    # 展示窗口
    w.show()

    # 程序进行循环等待状态
    app.exec()

(四)、创建带有输入框的窗口

import sys

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QLineEdit

if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = QWidget()

    # 设置窗口标题
    w.setWindowTitle("第一个PyQt")

    # 纯文本
    label = QLabel("账号", w)
    label.setGeometry(20, 20, 30, 20)

    # 文本框
    edit = QLineEdit(w)
    edit.setPlaceholderText("请输入账号")
    edit.setGeometry(55, 20, 200, 20)

    # 在窗口里面添加控件
    btn = QPushButton("注册", w)
    btn.setGeometry(50, 80, 70, 30)

    # 展示窗口
    w.show()

    # 程序进行循环等待状态
    app.exec()

(五)、创建可以调整窗口大小的窗口

import sys

from PyQt5.QtWidgets import QApplication, QWidget

if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = QWidget()

    # 设置窗口标题
    w.setWindowTitle("第一个PyQt")

    # 窗口的大小
    w.resize(300, 300)

    # 展示窗口
    w.show()

    # 程序进行循环等待状态
    app.exec()

(六)、创建在屏幕中间的窗口

import sys

from PyQt5.QtWidgets import QApplication, QWidget, QDesktopWidget

if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = QWidget()

    # 设置窗口标题
    w.setWindowTitle("第一个PyQt")

    # 窗口的大小
    w.resize(300, 300)

    # 将窗口设置在屏幕的左上角
    # w.move(0, 0)

    # 调整窗口在屏幕中央显示
    center_pointer = QDesktopWidget().availableGeometry().center()
    x = center_pointer.x()
    y = center_pointer.y()
    # w.move(x, y)
    # w.move(x-150, y-150)
    print(w.frameGeometry())
    print(w.frameGeometry().getRect())
    print(type(w.frameGeometry().getRect()))
    old_x, old_y, width, height = w.frameGeometry().getRect()
    w.move(x - width / 2, y - height / 2)

    # 展示窗口
    w.show()

    # 程序进行循环等待状态
    app.exec()

(七)、创建显示ICON图片的窗口

推荐几个ICON网站方便大家使用:

1.

免费和高级矢量图标、插图和 3D 插图icon-default.png?t=N7T8https://www.iconfinder.com/

2.Freepik | Create great designs, fastericon-default.png?t=N7T8https://www.freepik.com/

3.名词项目:一切的免费图标和库存照片 (thenounproject.com)icon-default.png?t=N7T8https://thenounproject.com/

4.

矢量图标和贴纸 - PNG、SVG、EPS、PSD 和 CSS (flaticon.com)icon-default.png?t=N7T8https://www.flaticon.com/

5.

iconfont-阿里巴巴矢量图标库icon-default.png?t=N7T8https://www.iconfont.cn/?spm=a313x.collections_index.i3.d4d0a486a.321e3a817DGgRQ

代码:

import sys

from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QWidget

if __name__ == '__main__':
    app = QApplication(sys.argv)

    # 创建一个QWidget
    w = QWidget()
    # 设置标题
    w.setWindowTitle("看看我图标帅吗")
    # 设置图标
    w.setWindowIcon(QIcon('panda.png'))
    # 显示QWidget
    w.show()

    app.exec()

五、Pyqt5的使用介绍

PyQt中有非常多的功能模块,开发中最常用的功能模块主要有三个:

  • QtCore:包含了核心的非GUI的功能。主要和时间、文件与文件夹、各种数据、流、URLs、mime类文件、进程与线程一起使用
  • QtGui:包含了窗口系统、事件处理、2D图像、基本绘画、字体和文字类
  • QtWidgets:包含了一些列创建桌面应用的UI元素

可以参考PyQt官网的所有模块,地址:Modules — PyQt Documentation v5.15.7

C++具体实现的API文档,地址:Qt Widgets C++ Classes | Qt Widgets 5.15.17

用到什么功能就它相关的api或者别人分享的使用心得,这是学习最快的方式

(一)、PyQt5布局管理:

  • QBoxLayout

水平布局(Horizontal layout)

垂直布局、

栅格布局(Grid Layout)

        是一种基于网格的布局系统,允许开发者在页面中创建复杂的布局结构。栅格布局使用一个网格来组织页面元素,将页面划分为一系列的行和列。开发者可以通过指定网格中的单元格位置和大小来控制元素的布局。
        栅格布局的主要特点是它可以非常灵活地定位和调整元素的位置和大小,而不需要依赖传统的文档流布局。栅格布局可以处理复杂的布局结构,并且可以自适应不同的屏幕尺寸和设备。同时,栅格布局也提供了丰富的布局调整方式,例如自适应、固定宽度、最大宽度、最小宽度等。
        在栅格布局中,通过使用grid容器来定义网格布局,通过grid-template-rows、grid-template-columns、grid-template-areas等属性来定义网格的行列布局。开发者可以使用grid-row、grid-column等属性来指定元素所占的网格单元格位置和大小。
        总的来说,栅格布局是一种强大的布局工具,可以帮助开发者快速创建复杂的布局结构,并且可以适应不同的屏幕尺寸和设备。

  • QGridLayout

  • QFormLayout

FormLayout是一种用于构建图形用户界面(GUI)中表单的布局管理器。它可以在表单中自动地安排各种控件(例如文本框、复选框、下拉框等)的位置和大小,以便它们以最优化的方式显示在表单上。

FormLayout的主要目的是简化表单的设计和排版工作,以及提高表单的可读性和易用性。使用FormLayout,设计人员可以轻松地创建各种不同类型的表单,例如登录表单、注册表单、数据输入表单等,而无需手动调整每个控件的位置和大小。
FormLayout可以根据表单中控件的类型和数量,自动地生成最佳的布局。它可以根据控件之间的相对关系和层次结构,调整每个控件的位置和大小,以确保它们之间的间距和对齐方式是一致的。这样,即使用户调整了表单的大小或缩放了它,控件的位置和大小也会随之自动调整,以适应新的尺寸。
FormLayout还提供了一些常用的功能,例如表单边距、控件间距、对齐方式、自动换行等。这些功能使得表单更加易于管理和修改,同时也提高了表单的可读性和易用性。
总之,FormLayout是一种非常有用的表单布局工具,可以使表单设计和排版变得更加高效和方便。使用FormLayout可以减少手动工作量,提高表单的质量和用户体验。

  • QStackedLayout


1.QBoxLayout

直译为:盒子布局

一般使用它的两个子类QHBoxLayout 和 QVBoxLayout 负责水平和垂直布局

垂直布局示例:

import sys
from PyQt5.QtWidgets import QApplication, QVBoxLayout, QWidget, QPushButton, QGroupBox, QMainWindow
from PyQt5.QtCore import Qt

class MyWindow(QWidget):
    def __init__(self):
        # 切记一定要调用父类的__init__方法,因为它里面有很多对UI空间的初始化操作
        super().__init__()

        # 设置大小
        self.resize(300, 300)
        # 设置标题
        self.setWindowTitle("垂直布局")

        # 垂直布局
        layout = QVBoxLayout()

        # 作用是在布局器中增加一个伸缩量,里面的参数表示QSpacerItem的个数,默认值为零
        # 会将你放在layout中的空间压缩成默认的大小
        # 下面的笔试1:1:1:2
        layout.addStretch(1)

        # 按钮1
        btn1 = QPushButton("按钮1")
        # 添加到布局器中
        # layout.addWidget(btn1, Qt.AlignmentFlag.AlignTop)
        layout.addWidget(btn1)

        layout.addStretch(1)

        # 按钮2
        btn2 = QPushButton("按钮2")
        # 添加到布局器
        layout.addWidget(btn2)

        layout.addStretch(1)

        # 按钮3
        btn3 = QPushButton("按钮3")
        # 添加到布局器
        layout.addWidget(btn3)

        layout.addStretch(2)

        self.setLayout(layout)

if __name__ == '__main__':
    app = QApplication(sys.argv)

    # 创建一个QWidget子类
    w = MyWindow()
    w.show()

    app.exec()

运行效果:

水平布局(Horizontal layout):

        是一种在用户界面中使用的布局方式,其中控件或窗口部件(widget)沿着水平方向排列。这意味着,每个控件或窗口部件都被放置在前一个控件或窗口部件的右侧,从而形成一个水平排列。
        水平布局常常用于在用户界面中放置多个控件或窗口部件,使它们在水平方向上对齐并占用相同的空间。水平布局在许多图形用户界面工具包中都得到了支持,例如 PyQt、Qt、JavaFX 等。
        水平布局通常与垂直布局(Vertical layout)结合使用,以便在用户界面中实现复杂的布局。例如,您可以使用水平布局将两个按钮水平排列在一起,然后使用垂直布局将这两个按钮与其他控件组合在一起,以便在用户界面中实现更复杂的布局。

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QGroupBox, QVBoxLayout, QHBoxLayout, QRadioButton


class MyWindow(QWidget):

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

    def init_ui(self):
        # 最外层的垂直布局,包含两部分:爱好和性别
        container = QVBoxLayout()

        # -----创建第1个组,添加多个组件-----
        # hobby 主要是保证他们是一个组。
        hobby_box = QGroupBox("爱好")
        # v_layout 保证三个爱好是垂直摆放
        v_layout = QVBoxLayout()
        btn1 = QRadioButton("抽烟")
        btn2 = QRadioButton("喝酒")
        btn3 = QRadioButton("烫头")
        # 添加到v_layout中
        v_layout.addWidget(btn1)
        v_layout.addWidget(btn2)
        v_layout.addWidget(btn3)
        # 把v_layout添加到hobby_box中
        hobby_box.setLayout(v_layout)

        # -----创建第2个组,添加多个组件-----
        # 性别组
        gender_box = QGroupBox("性别")
        # 性别容器
        h_layout = QHBoxLayout()
        # 性别选项
        btn4 = QRadioButton("男")
        btn5 = QRadioButton("女")
        # 追加到性别容器中
        h_layout.addWidget(btn4)
        h_layout.addWidget(btn5)
        # 添加到 box中
        gender_box.setLayout(h_layout)

        # 把爱好的内容添加到容器中
        container.addWidget(hobby_box)
        # 把性别的内容添加到容器中
        container.addWidget(gender_box)

        # 设置窗口显示的内容是最外层容器
        self.setLayout(container)


if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = MyWindow()
    w.show()

    app.exec()

运行效果:

  • 通过上面的示例,我们能够看到水平布局器与垂直布局器是可以混合使用即嵌套使用

2.QGridLayout

栅格布局(Grid Layout):网格布局,有的人称之为九宫格布局。

以下是GridLayout的一些重要特点:

        创建GridLayout对象:可以通过将QWidget作为参数传递给QGridLayout构造函数来创建一个GridLayout对象。然后可以使用addWidget()方法将控件添加到布局中。
        指定控件的位置:可以使用addWidget()方法的第二个和第三个参数来指定控件的位置。例如,addWidget(button, 0, 0)将button添加到第0行和第0列的单元格中。
        控件的大小和跨度:可以使用addWidget()方法的第四个和第五个参数来指定控件在行和列中所占的单元格数量。例如,addWidget(label, 0, 0, 1, 2)将label添加到第0行和第0列的单元格中,并让它跨越第0列和第1列的两个单元格。
        添加空白单元格:可以使用addSpacing()方法添加空白的单元格,从而调整控件之间的距离。
        对齐方式:可以使用setAlignment()方法设置控件在单元格中的对齐方式。可以指定水平和垂直方向的对齐方式,也可以将对齐方式设置为水平和垂直方向的组合。
        自动调整大小:可以使用setColumnStretch()和setRowStretch()方法来设置单元格的大小。可以使用addStretch()方法添加一个伸缩项,以便在窗口大小改变时自动调整大小。

2-1:QGridLayout简单介绍

GridLayout(网格布局)是一种PyQt5中的布局管理器,用于将控件以网格的形式排列在窗口中。每个单元格可以包含一个控件,且所有单元格大小相等。

在GridLayout中,控件被按照行和列的方式排列。行和列从0开始编号。控件可以跨越多个行和列,这是通过指定控件的位置以及它在行和列中所占的单元格数量来实现的。

2-2:QGridLayout案例分析(简单计算器实现)

        在这个例子中,我们创建了一个计算器窗口,并使用QGridLayout将所有控件排列成表格形式。我们使用QPushButton创建了所有数字和运算符按钮,并将它们添加到网格布局中。我们还使用QLineEdit创建了结果文本框,并将其放置在布局的顶部。
当用户单击按钮时,我们使用on_button_clicked()方法来更新结果文本框。如果用户单击等号按钮,我们计算表达式并在文本框中显示结果。如果表达式无效,则在文本框中显示“Error”。

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QGridLayout, QPushButton, QLineEdit


class CalculatorWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        # 设置窗口属性
        self.setWindowTitle("Calculator")
        self.setFixedSize(300, 300)

        # 设置中心窗口
        central_widget = QWidget(self)
        self.setCentralWidget(central_widget)

        # 创建布局
        grid_layout = QGridLayout()
        central_widget.setLayout(grid_layout)

        # 添加文本框
        self.result_line_edit = QLineEdit()
        # self.result_line_edit.setAlignment(Qt.AlignRight)
        self.result_line_edit.setReadOnly(True)
        grid_layout.addWidget(self.result_line_edit, 0, 0, 1, 4)

        # 添加按钮
        buttons = [
            "7", "8", "9", "/",
            "4", "5", "6", "*",
            "1", "2", "3", "-",
            "0", ".", "=", "+"
        ]
        positions = [(i, j) for i in range(1, 5) for j in range(4)]
        for position, button_label in zip(positions, buttons):
            button = QPushButton(button_label)
            button.setMaximumWidth(50)
            button.clicked.connect(self.on_button_clicked)
            grid_layout.addWidget(button, *position)

    def on_button_clicked(self):
        button = self.sender()
        button_label = button.text()

        if button_label == "=":
            try:
                result = str(eval(self.result_line_edit.text()))
            except (SyntaxError, ZeroDivisionError):
                result = "Error"
            self.result_line_edit.setText(result)
        else:
            self.result_line_edit.setText(self.result_line_edit.text() + button_label)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    calculator = CalculatorWindow()
    calculator.show()
    sys.exit(app.exec_())

运行效果:

3.QFormLayout

一般适用于提交数据form表单。比如: 登录,注册类似的场景

import sys

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QVBoxLayout, QFormLayout, QLineEdit, QPushButton, QApplication, QWidget


class MyWindow(QWidget):

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

    def init_ui(self):
        # 设定当前Widget的宽高(可以拉伸大小)
        # self.resize(300, 200)
        # 禁止改变宽高(不可以拉伸)
        self.setFixedSize(300, 150)

        # 外层容器
        container = QVBoxLayout()

        # 表单容器
        form_layout = QFormLayout()

        # 创建1个输入框
        edit = QLineEdit()
        edit.setPlaceholderText("请输入账号")
        form_layout.addRow("账号:", edit)

        # 创建另外1个输入框
        edit2 = QLineEdit()
        edit2.setPlaceholderText("请输入密码")
        form_layout.addRow("密码:", edit2)

        # 将from_layout添加到垂直布局器中
        container.addLayout(form_layout)

        # 按钮
        login_btn = QPushButton("登录")
        login_btn.setFixedSize(100, 30)

        # 把按钮添加到容器中,并且指定它的对齐方式
        container.addWidget(login_btn, alignment=Qt.AlignRight)

        # 设置当前Widget的布局器,从而显示这个布局器中的子控件
        self.setLayout(container)


if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = MyWindow()
    w.show()

    app.exec()

运行效果:

4.QStackedLayout

提供了多页面切换的布局,一次只能看到一个界面。 抽屉布局

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QStackedLayout, QLabel


class Window1(QWidget):
    def __init__(self):
        super().__init__()
        QLabel("我是抽屉1要显示的内容", self)
        self.setStyleSheet("background-color:green;")


class Window2(QWidget):
    def __init__(self):
        super().__init__()
        QLabel("我是抽屉2要显示的内容", self)
        self.setStyleSheet("background-color:red;")


class MyWindow(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.create_stacked_layout()
        self.init_ui()

    def create_stacked_layout(self):
        # 创建堆叠(抽屉)布局
        self.stacked_layout = QStackedLayout()
        # 创建单独的Widget
        win1 = Window1()
        win2 = Window2()
        # 将创建的2个Widget添加到抽屉布局器中
        self.stacked_layout.addWidget(win1)
        self.stacked_layout.addWidget(win2)

    def init_ui(self):
        # 设置Widget大小以及固定宽高
        self.setFixedSize(300, 270)

        # 1. 创建整体的布局器
        container = QVBoxLayout()

        # 2. 创建1个要显示具体内容的子Widget
        widget = QWidget()
        widget.setLayout(self.stacked_layout)
        widget.setStyleSheet("background-color:grey;")

        # 3. 创建2个按钮,用来点击进行切换抽屉布局器中的Widget
        btn_press1 = QPushButton("抽屉1")
        btn_press2 = QPushButton("抽屉2")
        # 给按钮添加事件(即点击后要调用的函数)
        btn_press1.clicked.connect(self.btn_press1_clicked)
        btn_press2.clicked.connect(self.btn_press2_clicked)

        # 4. 将需要显示的空间添加到布局器中
        container.addWidget(widget)
        container.addWidget(btn_press1)
        container.addWidget(btn_press2)

        # 5. 设置当前要显示的Widget,从而能够显示这个布局器中的控件
        self.setLayout(container)

    def btn_press1_clicked(self):
        # 设置抽屉布局器的当前索引值,即可切换显示哪个Widget
        self.stacked_layout.setCurrentIndex(0)

    def btn_press2_clicked(self):
        # 设置抽屉布局器的当前索引值,即可切换显示哪个Widget
        self.stacked_layout.setCurrentIndex(1)


if __name__ == "__main__":
    app = QApplication(sys.argv)

    win = MyWindow()
    win.show()

    app.exec()

运行效果:

(二)、窗口分类

在Qt中,生成窗口有三种方式: QWidget | QMainWindow | QDialog

1.QWidget

控件和窗口的父类 ,自由度高(什么都东西都没有),没有划分菜单、工具栏、状态栏、主窗口 等区域

import  sys

from PyQt5.QtWidgets import QWidget, QLabel , QApplication

class mywnd(QWidget):

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

    def initUI(self):
        label = QLabel("这是文字~~" )
        label.setStyleSheet("font-size:30px;color:red")
        label.setParent(self)

if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = mywnd()

    #设置窗口标题
    w.setWindowTitle("qwidget")

    # 展示窗口
    w.show()

    # 程序进行循环等待状态
    app.exec()

运行效果:

2.QMainWindow

QWidget的子类,包含菜单栏,工具栏,状态栏,标题栏等,中间部分则为主窗口区域

import sys

from PyQt5.QtWidgets import QMainWindow, QLabel, QApplication


class MyWindow(QMainWindow):

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

    def init_ui(self):
        label = QLabel("这是文字~~")
        label.setStyleSheet("font-size:30px;color:red")

        # 调用父类中的menuBar,从而对菜单栏进行操作
        menu = self.menuBar()
        # 如果是Mac的话,菜单栏不会在Window中显示而是屏幕顶部系统菜单栏位置
        # 下面这一行代码使得Mac也按照Windows的那种方式在Window中显示Menu
        menu.setNativeMenuBar(False)

        file_menu = menu.addMenu("文件")
        file_menu.addAction("新建")
        file_menu.addAction("打开")
        file_menu.addAction("保存")

        edit_menu = menu.addMenu("编辑")
        edit_menu.addAction("复制")
        edit_menu.addAction("粘贴")
        edit_menu.addAction("剪切")

        # 设置中心内容显示
        self.setCentralWidget(label)


if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = MyWindow()
    # 设置窗口标题
    w.setWindowTitle("我是窗口标题....")
    # 展示窗口
    w.show()

    # 程序进行循环等待状态
    app.exec()

运行效果:

3.QDialog

对话框窗口的基类

import sys

from PyQt5.QtWidgets import QDialog, QPushButton, QApplication


class MyDialog(QDialog):

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

    def init_ui(self):
        ok_btn = QPushButton("确定", self)
        ok_btn.setGeometry(50, 50, 100, 30)


if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = MyDialog()
    # 设置窗口标题
    w.setWindowTitle("对话框")
    # 展示窗口
    w.show()

    # 程序进行循环等待状态
    app.exec()

运行效果:

(三)、信号与槽

1.说明

信号是 Qt的核心内容

2.信号

其实就是事件(按钮点击 、内容发生改变 、窗口的关闭事件) 或者是 状态 (check选中了, togglebutton 切换。)

当程序触发了某种状态或者发生了某种事件(比如:按钮被点击了, 内容改变等等),那么即可发射出来一个信号

3.槽

若想捕获这个信号,然后执行相应的逻辑代码,那么就需要使用到  , 实际上是一个函数, 当信号发射出来后,会执行与之绑定的函数

4.将信号和槽链接

为了能够实现,当点击某个按钮时执行某个逻辑,需要把具体的信号和具体的函数绑定到一起.

操作大体流程如下

对象.信号.connect(槽函数)

5.案例

1-功能:接收信号
import sys

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton


class MyWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        # 更改当前Widge的宽高
        self.resize(500, 300)
        # 创建一个按钮
        btn = QPushButton("点我点我", self)
        # 设置窗口位置、宽高
        btn.setGeometry(200, 200, 100, 30)
        # 将按钮被点击时触发的信号与我们定义的函数(方法)进行绑定
        # 注意:这里没有(),即写函数的名字,而不是名字()
        btn.clicked.connect(self.click_my_btn)

    def click_my_btn(self, arg):
        # 槽函数,点击按钮则调用该函数
        # 这里的参数正好是信号发出,传递的参数
        print("点击按钮啦~", arg)


if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = MyWindow()
    w.show()

    app.exec()
运行效果:
2-自定义信号
import sys
import time

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *


class MyWindow(QWidget):
    # 声明一个信号 只能放在函数的外面
    my_signal = pyqtSignal(str)

    def __init__(self):
        super().__init__()
        self.init_ui()
        self.msg_history = list()  # 用来存放消息

    def init_ui(self):
        self.resize(500, 200)

        # 创建一个整体布局器
        container = QVBoxLayout()

        # 用来显示检测到漏洞的信息
        self.msg = QLabel("")
        self.msg.resize(440, 15)
        # print(self.msg.frameSize())
        self.msg.setWordWrap(True)  # 自动换行
        self.msg.setAlignment(Qt.AlignTop)  # 靠上
        # self.msg.setStyleSheet("background-color: yellow; color: black;")

        # 创建一个滚动对象
        scroll = QScrollArea()
        scroll.setWidget(self.msg)

        # 创建垂直布局器,用来添加自动滚动条
        v_layout = QVBoxLayout()
        v_layout.addWidget(scroll)

        # 创建水平布局器
        h_layout = QHBoxLayout()
        btn = QPushButton("开始检测", self)
        # 绑定按钮的点击,点击按钮则开始检测
        btn.clicked.connect(self.check)
        h_layout.addStretch(1)  # 伸缩器
        h_layout.addWidget(btn)
        h_layout.addStretch(1)

        # 操作将要显示的控件以及子布局器添加到container
        container.addLayout(v_layout)
        container.addLayout(h_layout)

        # 设置布局器
        self.setLayout(container)

        # 绑定信号和槽
        self.my_signal.connect(self.my_slot)

    def my_slot(self, msg):
        # 更新内容
        print(msg)
        self.msg_history.append(msg)
        self.msg.setText("<br>".join(self.msg_history))
        self.msg.resize(440, self.msg.frameSize().height() + 15)
        self.msg.repaint()  # 更新内容,如果不更新可能没有显示新内容

    def check(self):
        for i, ip in enumerate(["192.168.1.%d" % x for x in range(1, 255)]):
            msg = "模拟,正在检查 %s 上的漏洞...." % ip
            # print(msg)
            if i % 5 == 3:
                # 表示发射信号 对象.信号.发射(参数)
                self.my_signal.emit(msg + "【发现漏洞】")
            time.sleep(0.01)


if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = MyWindow()
    w.show()

    app.exec()
运行效果:

3-思考与实操

左边的控件是 QDial , 右边的控件是 QSpinBox 。两者相互关联,转动刻度右边的数字随之改变,改变右边的数字,左边的刻度盘也跟着转到指定位置。

利用信号/槽编辑器完成信号的传输。

运行效果:

可能会用上的链接:Qt Widgets专栏

【类】QDialicon-default.png?t=N7T8https://blog.csdn.net/hitzsf/article/details/113097550

(四)、QT Designer介绍

        纯靠代码来编写界面,效率属实是有点低,今天我们用另外一个辅助设计图形化的软件 QT Designer

   Qt designer,即 Qt设计师,是一个强大、灵活的可视化GUI 设计工具,可以帮助我们加快开发PyQt程序的速度。Qt designer是专门用来制作PyQt程序中U界面的工具,它生成的UI界面是一个后缀为.ui的文件。该文件使用起来非常简单,可以通过命令将.ui文件转换成.py格式的文件,并被其他Python文件引用;也可以像上节搭建环境一样,配置工具,直接操作,不过其本质,都是运行对应的工具转换程序实现的。

  Qt designer符合MVC(模型—视图一控制器)设计模式,做到了显示和业务逻辑的分离。

  Qt designer具有以下优点。

  使用简单,通过拖曳和点击就可以完成复杂的界面设计,而且还可以随时预览查看效果图。

  转换Python文件方便。Qt designer可以将设计好的用户界面保存为.ui文件,其实是XML格式的文本文件。为了在 PyQt中使用.ui文件,可以通过 pyuic5命令将.ui文件转换为.py文件件,然后将.py文件引入到自定义的Python代码中。 

1.新建主窗口 

        在Qt designer 的安装路径下双击designer.exe文件,打开PyQt 5的 Qt designer,会自动弹出“新建窗体”对话框,如图所示。在模板选项中,最常用的就是Widget(通用窗口)和 Main Window(主窗口)。在PyQt 5中 Widget被分离出来,用来替代 Dialog,并将Widget放入了QtWidget模块库中。

        模板选择“Main Window”,创建一个主窗口,保存并命名为firstMainWin.ui,如图所示,主窗口默认添加了菜单栏、工具栏和状态栏。 

        在菜单栏中选择“窗体”→“预览”,或者按“Ctrl+R”快捷键,就可以看到窗口的预览效果了。

2.主要功能区域介绍 

  工具箱区域:提供GUI界面开发使用的各种基本控件,如单选框、文本框等。可以拖动到新创建的主程序界面。

  主界面区域:用户放置各种从工具箱拖过来的各种控件。模板选项中最常用的就是Widget(通用窗口)和MainWindow(主窗口)。二者区别主要是Widget窗口不包含菜单栏、工具栏等。可以分别创建对比看看。

  对象查看器 区域:查看主窗口放置的对象列表。

  属性编辑器 区域: 提供对窗口、控件、布局的属性编辑功能。比如修改控件的显示文本、对象名、大小等。

  信号/槽编辑器 区域:编辑控件的信号和槽函数,也可以添加自定义的信号和槽函数。

      (1)  Widget Box(控件工具箱)

        Widget Box控件工具箱是按照控件作用类别进行划分的。这里作为实现入门级界面实现,主要介绍最常使用的控件及控件对象相关函数。函数方法知道怎么获取控件输入内容以及如何将后台操作结果输出到界面控件显示的主要函数就可以了。

1.显示控件(Display widgets):

      Lable:文本标签,显示文本,可以用来标记控件。

      Text Browser:显示文本控件。用于后台命令执行结果显示。

2.输入控件(Input widgets):提供与用户输入交互

      Line Edit:单行文本框,输入单行字符串。控件对象常用函数为Text() 返回文本框内容,用于获取输入。setText() 用于设置文本框显示。

      Text Edit:多行文本框,输入多行字符串。控件 对象常用函数同Line Edit控件。

  Combo Box:下拉框列表。用于输入指定枚举值。

3.按钮控件(Buttons) :供用户选择与执行

        Push Button:命令按钮。常见的确认、取消、关闭等按钮就是这个控件。clicked信号一定要记住。clicked信号就是指鼠标左键按下然后释放时会发送信号,从而触发相应操作。

        Radio Button:单选框按钮。

        Check Box:多选框按钮。

4.Containers

5.Item widgets

6.Spacers——Layouts

(2) 设计窗口

(3)菜单栏

(4)工具栏


3.pyqt5工具包介绍

        Qt Designer:可以通过Qt Designer来编写UI界面,Qt Designer的设计符合MVC的架构,其实现了视图和逻辑的分离,从而实现了开发的便捷。Qt Designer中的操作方式十分灵活,其通过拖拽的方式放置控件可以随时查看控件效果。Qt Designer随PyQt5-tools包一起安装,其安装路径在 “Python安装路径\Lib\site-packages\qt5_applications\Qt\bin”下,注意这个路径是最新路径!
        PyUIC:Qt Designer生成的.ui文件(实质上是XML格式的文件)可以通过pyuic5工具转换成.py文件。
        PyRcc:在使用PyQt开发界面时,在Qt Designer中使用的图片等资源需要将其编译为py文件,这时需要用到PyRcc工具方便地将qrc文件转换为py文件。

后面这两个工具包PyUIC和PyRcc都在 工程目录下的Scripts文件里面

实在找不到的同学,可以在工程根目录下搜索,然后记住这个路径,后面会用到。

采用Qt designer 工具设计的界面文件默认为.ui文件,描述了窗口中控件的属性列表和布局显示。.ui 文件里面包含的内容是按照XML(可扩展标记语言)格式处理的。


4.将.ui文件转换为.py文件

使用Qt designer设计的用户界面默认保存为.ui文件,其内容结构类似于XML,但这种文件并不是我们想要的,我们想要的是.py文件,所以还需要使用其他方法将.ui文件转换为.py文件。本文提供了2种方法。 

(1)通过打开Tools->External Tools->PyUIC将.ui文件转换为.py文件。 

使用这个方法前需要将这个工具 添加到外部工具里面

Name: PyUIC

Program : C:\AppData\Local\Programs\Python\Python38-32\python.exe
 # 当前Python目录,请根据实际修改

Arguments: -m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py

Working directory: $FileDir$

使用UIC工具转换完成以后,需要将下面的代码复制到转换后的py文件尾部再运行!!!

from PyQt5.QtWidgets import QMainWindow,QApplication
import sys
if __name__ == '__main__':
    app = QApplication(sys.argv)

    window = QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(window)

    window.show()
    sys.exit(app.exec_())
(2)通过命令行把.ui文件转换为.py文件 

 使用命令行pyuic5 -o login.py login.ui转换成.py文件。

调用格式为pyuic5 -o {输出文件名} {输入designer设计好的.ui后缀界面文件}。执行结果如下

python -m PyQt5.uic.pyuic demo.ui -o demo.py

#-o是操作参数,表示要生成一个文件
#destination.py是要生成的.py文件
#source.ui是在此之前用QtCreator生成的包含UI设计的.ui文件
(3)将资源文件转换成.py文件

1.使用RCC工具

Name: PyRCC
Program : C:\Python38\Scripts\pyrcc5.exe # 当前rcc工具目录,请根据实际修改
Arguments: $FileName$ -o $FileNameWithoutExtension$_rc.py
Working directory: $FileDir$

2.使用命令

	
pyrcc4 -o resource.py resource.qrc

6.动态加载ui文件

6-1:动态ui文件的使用

利用这种办法可以直接调用你所制作的ui而不需要每一次都将你的ui文件转换成py文件。

代码:

"""
动态加载ui文件
"""

import sys
from PyQt5.QtWidgets import QApplication
from PyQt5 import uic

if __name__ == '__main__':
    app = QApplication(sys.argv)

    ui = uic.loadUi("./test.ui")
#这里的test.ui可以改成你需要的名称

    # 展示窗口
    ui.show()

    app.exec()

ui设计:


6-2:进阶案例
import sys

from PyQt5.QtWidgets import *
from PyQt5 import uic


class MyWindow(QWidget):

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

    def init_ui(self):
        self.ui = uic.loadUi("./login.ui")
        # print(self.ui.__dict__)  # 查看ui文件中有哪些控件

        # 提取要操作的控件
        self.user_name_qwidget = self.ui.lineEdit  # 用户名输入框
        self.password_qwidget = self.ui.lineEdit_2  # 密码输入框
        self.login_btn = self.ui.pushButton  # 登录按钮
        self.forget_password_btn = self.ui.pushButton_2  # 忘记密码按钮
        self.textBrowser = self.ui.textBrowser  # 文本显示区域

        # 绑定信号与槽函数
        self.login_btn.clicked.connect(self.login)

    def login(self):
        """登录按钮的槽函数"""
        user_name = self.user_name_qwidget.text()
        password = self.password_qwidget.text()
        if user_name == "admin" and password == "123456":
            self.textBrowser.setText("欢迎%s" % user_name)
            self.textBrowser.repaint()
        else:
            self.textBrowser.setText("用户名或密码错误....请重试")
            self.textBrowser.repaint()


if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = MyWindow()
    # 展示窗口
    w.ui.show()

    app.exec()

(五)、多线程介绍

1.引入

import sys
import time

from PyQt5.QtWidgets import *
from PyQt5 import uic


class MyWindow(QWidget):

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

    def init_ui(self):
        self.ui = uic.loadUi("./login.ui")
        # print(self.ui.__dict__)  # 查看ui文件中有哪些控件

        # 提取要操作的控件
        self.user_name_qwidget = self.ui.lineEdit  # 用户名输入框
        self.password_qwidget = self.ui.lineEdit_2  # 密码输入框
        self.login_btn = self.ui.pushButton  # 登录按钮
        self.forget_password_btn = self.ui.pushButton_2  # 忘记密码按钮
        self.textBrowser = self.ui.textBrowser  # 文本显示区域

        # 绑定信号与槽函数
        self.login_btn.clicked.connect(self.login)

    def login(self):
        """登录按钮的槽函数"""
        user_name = self.user_name_qwidget.text()
        password = self.password_qwidget.text()

        for i in range(10):
            print("正在登录服务器....%d" % (i + 1))
            time.sleep(1)

        if user_name == "admin" and password == "123456":
            self.textBrowser.setText("欢迎%s" % user_name)
            self.textBrowser.repaint()
        else:
            self.textBrowser.setText("用户名或密码错误....请重试")
            self.textBrowser.repaint()


if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = MyWindow()
    # 展示窗口
    w.ui.show()

    app.exec()

运行效果:

2.pyqt使用线程

import sys
import time

from PyQt5 import uic
from PyQt5.Qt import QApplication, QWidget, QThread


class MyThread(QThread):
    def __init__(self):
        super().__init__()

    def run(self):
        for i in range(10):
            print("是MyThread线程中执行....%d" % (i + 1))
            time.sleep(1)


class MyWin(QWidget):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.ui = uic.loadUi("./thread-1.ui")

        # 从ui文件中加载控件
        lineedit = self.ui.lineEdit
        btn1 = self.ui.pushButton
        btn2 = self.ui.pushButton_2

        # 给2个按钮绑定槽函数
        btn1.clicked.connect(self.click_1)  # 绑定槽函数
        btn2.clicked.connect(self.click_2)  # 绑定槽函数

    def click_1(self):
        for i in range(10):
            print("是UI线程中执行....%d" % (i + 1))
            time.sleep(1)

    def click_2(self):
        self.my_thread = MyThread()  # 创建线程
        self.my_thread.start()  # 开始线程


if __name__ == "__main__":
    app = QApplication(sys.argv)
    myshow = MyWin()
    myshow.ui.show()
    app.exec()

运行效果:

(六)、程序打包

1.使用pyinstall


python提供了多种方法用于将普通的*.py程序文件编译成exe文件(有时这里的“编译”也称作“打包”)。exe文件即可执行文件,打包后的*.exe应用不用依赖python环境,可以在他人的电脑上运行。

pyinstaller是一个第三方模块,专用于python程序的exe打包。此外python还有一些别的方法进行打包,但是pyinstaller打包最强大而且好用。

pyinstaller的官网是:https://pyinstaller.org/

安装软件包:

pip install pyinstaller

基本语法:

pyinstaller myscript.py
#myscript.py为你想打包的程序

推荐使用:

pyinstaller -F -w myscript.py

#-F 生成单个可执行程序
#-w 执行程序时不显示命令框,更美观
#myscript.py为你想打包的程序
参数名描述可执行命令
-D文件夹模式。在打包完成后生成一个文件夹,其中包含一个exe文件和一个包含若干依赖文件的文件夹(详见上文)。

pyinstaller -D tset.py

-F单文件模式。在打包完成后只会生成一个单独的exe文件(详见上文)新手推荐。 pyinstaller -F tset.py
--add-data <SRC;DEST or SRC:DEST>指定一个文件夹或文件(非二进制),将其嵌入到exe中。
--add-binary <SRC;DEST or SRC:DEST>和--add-data类似,不过指定的文件夹或文件是二进制的

-p DIR

--paths DIR

提供一个路径进行搜索并且导入里面的模块(不同的路径使用路径分隔符os.pathsep分隔开,或者多次使用这个参数)。

这可以解决有时候第三方模块找不到的问题。

--hidden-import MODULENAME

--hiddenimport MODULENAME

需要进行额外导入的模块。当pyinstaller在程序中找不到一些模块时,需要你额外指定。这个参数可以多次使用,可以解决一些模块找不到的问题。
--splash IMAGE_FILE添加一个启动画面(图片文件)路径,在程序运行前显示指定的启动图片,起到加载提示的效果。
-c, --console, --nowindowed
打包程序运行后出现一个黑色的控制台窗口(默认)
-w, --windowed, --noconsole打包程序运行后隐藏控制台窗口(美观) pyinstaller -w tset.py

-i ,*.ico

设置打包后exe程序的图标(只能在Windows和macOS上使用)建议图片大小32*32或者16*16 pyinstaller -i 252.ico tset.py
--disable-windowed-traceback禁用异常提示(只能在Windows和macOS上使用)
--help, -h打印pyinstaller的帮助信息并退出

关于这个打包软件这里推荐一个博客大家可以一起学习:

Python pyinstaller打包exe最完整教程-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_48979387/article/details/132359366


六、其他

(一)补充


(二)使用QT Designer制作网络摄像头监控界面

1.功能需求

(1)监控界面设计

流畅预览监控画面

完成照片采集

(2)温湿度数据采集

2.软件、硬件、云平台介绍

(1)软件介绍

使用python3和QT Designer制作图形化界面,并打包成可执行文件

(2)硬件介绍

使用海康威视网络摄像头

温湿度采集模块

(3)云平台介绍

3.软件搭建

4.云平台调试


(三)案例

1.功能需求

(1)界面设计
(2)数据采集

2.软件、硬件、云平台介绍

(1)软件介绍
(2)硬件介绍
(3)云平台介绍

3.软件搭建

4.云平台调试


总结

截止2024/8/6,文章基本成型,大体上已经完成,只是排版上还需要下一点功夫,关于PyQT的使用先就告一段落了,之后会加紧完善其他的博客,敬请关注,如果文章能帮助到你请点个赞吧,感谢各位的浏览。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值