【PyQt5】PyQt5快速入门——学习笔记

视频连接 PyQt5 快速入门

安装PyQt

进入anaconda对应的环境下,

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

第一个PyQt程序

一个带界面的程序

# 第一个PyQt程序
import sys 
from PyQt5.QtWidgets import QApplication, QWidget

if __name__ == '__main__':
    app = QApplication(sys.argv) # 创建了一个QApplication对象,传入当前的环境参数,有且只有一个
    w = QWidget() # QWidget对象,用于创建顶级窗口,用于展示界面
    # 设置窗口标题
    w.setWindowTitle("第一个PyQt")
    # 展示窗口
    w.show()
    # 程序进入循环等待状态
    app.exec_() # 调用exec_(),进入事件检测循环

在这里插入图片描述

模块介绍

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

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

基本UI

窗口内的所有控件,若想在窗口中显示,都需要表示它的父亲是谁,而不能直接使用show函数显示

1. 按钮

按钮对应的控件名称为QPushButton,位于PyQt5.Qtwidgets里面

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

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = QWidget()
    # 设置窗口标题
    w.setWindowTitle("第一个PyQt程序")
    # 在窗口里面添加控件
    button = QPushButton("按钮")
    # 设置按钮的父亲是当前窗口,等于是添加到窗口中显示
    button.setParent(w)
    # 展示窗口
    w.show()
    # 程序进入循环等待状态
    app.exec_()

在这里插入图片描述

2. 文本

纯文本控件名称为QLabel,位于PyQt5.Qtwidgets里面
纯文本控件仅仅作为标识显示而已,类似输入内容前的一段标签提示(账号、密码)

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

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = QWidget()
    # 设置窗口标题
    w.setWindowTitle("第一个PyQt程序")
    # 在窗口里面添加Label(纯文本),再创建的时候指定父对象
    label = QLabel("账号: ", w)
    # 设置位置与大小:x, y, w, h
    label.setGeometry(20, 20, 30, 30)
    # 展示窗口
    w.show()
    # 程序进入循环等待状态
    app.exec_()

在这里插入图片描述

3.输入框

输入框的控件名称为 QLineEdit,位于 PyQt5.Qtwidgets 里面

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

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = QWidget()
    # 设置窗口标题
    w.setWindowTitle("第一个PyQt程序")
    # 在窗口里面添加Label(纯文本),再创建的时候指定父对象
    label = QLabel("账号: ", w)
    # 设置位置与大小:x, y, w, h
    label.setGeometry(55,20, 30, 20)
    # 文本框
    edit = QLineEdit(w)
    edit.setPlaceholderText("请输入账号")
    label.setGeometry(50, 80, 70, 30)
    # 展示窗口
    w.show()
    # 程序进入循环等待状态
    app.exec_()

在这里插入图片描述

4. 调整窗口的大小、位置

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()  # 获得屏幕中央的点 PyQt5.QtCore.QPoint(959, 519)
    x = center_pointer.x()
    y = center_pointer.y()
    old_x, old_y, width, height = w.frameGeometry().getRect()
    w.move(x - width / 2, y - width / 2)
    # 展示窗口
    w.show()
    # 程序进入循环等待状态
    app.exec_()

5. 设置窗口的图标icon

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

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = QWidget()
    # 设置窗口标题
    w.setWindowTitle("设置图标")
    # 设置图标
    w.setWindowIcon(QIcon('SVM.png'))
    # 展示窗口
    w.show()
    # 程序进入循环等待状态
    app.exec_()

在这里插入图片描述

布局

在Qt里面布局分为四个大类

  • QBoxLayout
  • QGridLayout
  • QFormLayout
  • QStackedLayout

1、QBoxLayout垂直

直译为:盒子布局
一般使用它的两个子类 QHBoxLayoutQVBoxLayout负责水平和垂直布局

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

class MyWindow(QWidget):
    def __init__(self):
        super().__init__()  # 调用父类的__init__方法
        # 设置大小
        self.resize(300, 300)
        # 设置标题
        self.setWindowTitle("垂直布局")
        # 垂直布局
        layout = QVBoxLayout()  # 创建一个布局器
        layout.addStretch(2)
        # 按钮1
        button_1 = QPushButton("按钮1")
        layout.addWidget(button_1)
        layout.addStretch(2)
        # 按钮2
        button_2 = QPushButton("按钮2")
        layout.addWidget(button_2)
        layout.addStretch(2)
        # 按钮3
        button_3 = QPushButton("按钮3")
        layout.addWidget(button_3)
        # 让当前的窗口使用这个布局规则(布局器)
        layout.addStretch(2)  # 添加一个伸缩器,里面的参数为占几份
        self.setLayout(layout)  # 默认平均分配

if __name__ == '__main__':
    app = QApplication(sys.argv)
    # 创建一个MyWindow子类
    w = MyWindow()
    # 展示窗口
    w.show()
    # 程序进入循环等待状态
    app.exec_()

在这里插入图片描述

2、QBoxLayout水平

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

class MyWindow(QWidget):
    def __init__(self):
        super().__init__()  # 调用父类的__init__方法
        self.init_ui()

    def init_ui(self):
        # 设置标题
        self.setWindowTitle("水平布局和垂直布局")
        self.resize(150, 200)
        # 最外层的垂直布局,包含两部分:爱好和性别
        container = QVBoxLayout()

        # --- 创建第一个组,添加多个组件 ---
        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)

        # --- 创建第二个组,添加多个组件 ---
        gender_box = QGroupBox("性别")
        # h_layout 爱好是水平布局
        h_layout = QHBoxLayout()
        btn4 = QRadioButton("男")
        btn5 = QRadioButton("女")
        # 将三个圆形按钮添加到v_layout中
        h_layout.addWidget(btn4)
        h_layout.addWidget(btn5)
        # 将v_layout添加到hobby_box中
        gender_box.setLayout(h_layout)

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

        # 设置窗口显示的内容是最外层容器
        self.setLayout(container)  # 默认平均分配

if __name__ == '__main__':
    app = QApplication(sys.argv)
    # 创建一个MyWindow子类
    w = MyWindow()
    # 展示窗口
    w.show()
    # 程序进入循环等待状态
    app.exec_()

在这里插入图片描述

3、GridLayout

网格布局:有人成为九宫格布局

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

class MyWindow(QWidget):
    def __init__(self):
        super().__init__()  # 调用父类的__init__方法
        self.init_ui()  # 自己的方法

    def init_ui(self):
        # 设置标题
        self.setWindowTitle("计算器")
        # 准备数据
        data = {
            0: ["7", "8", "9", "+", "("],
            1: ["4", "5", "6", "-", ")"],
            2: ["1", "2", "3", "*", "<-"],
            3: ["0", ".", "=", "/", "C"]
        }

        # 整体垂直布局
        layout = QVBoxLayout()

        # 输入框
        edit = QLineEdit()
        edit.setPlaceholderText("请输入内容")  # 没输入东西时显示的内容
        # 把输入框添加到整体布局中
        layout.addWidget(edit)

        # 网格布局
        grid = QGridLayout()
        # 循环创建追加进去
        for line_number, line_data in data.items():
            # 此时line_number是第几行,line_data是当前行的数据
            for col_number, number in enumerate(line_data): # 返回索引和值
                btn = QPushButton(number)
                grid.addWidget(btn, line_number, col_number)
        # 把网络布局追加到整体布局中
        layout.addLayout(grid)
        # 设置窗口显示的内容是最外层容器
        self.setLayout(layout)  # 默认平均分配


if __name__ == '__main__':
    app = QApplication(sys.argv)
    # 创建一个MyWindow子类
    w = MyWindow()
    # 展示窗口
    w.show()
    # 程序进入循环等待状态
    app.exec_()

在这里插入图片描述

4、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()

在这里插入图片描述

5、QStackedLayout

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

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


class Window1(QWidget):
    def __init__(self):
        super().__init__()
        QLabel("我是抽屉1要显示的内容", self)  # QLabel用于显示文本或图像的窗口部件
        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. 创建一个要显示具体内容的子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 QApplication, QMainWindow, QLabel

class MyWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        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)
    win = MyWindow()
    win.setWindowTitle("窗口标题")
    win.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. 信号(signal)

其实就是事件(按钮点击、内容发生改变、窗口的关闭事件)或者是状态(check选中了,togglebutton切换。)
当程序触发了某种状态或者发生了某种事件(比如︰按钮被点击了,内容改变等等) ﹐那么即可发射出来一个信号

2. 槽(slot)

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

3. 将信号与槽连接

为了能够实现,当点击某个按钮时执行某个逻辑,需要把具体的信号和具体的函数绑定到一起。操作大体流程如下

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

在这里插入图片描述

案例1

import sys
import time

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

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

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

    def init_ui(self):
        self.resize(300, 200)
        btn = QPushButton("开始检查", self)
        btn.setGeometry(100, 150, 100, 30)

        # 绑定按钮的点击,点击按钮则开始检测
        btn.clicked.connect(self.check)

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

    def my_slot(self, msg):
        print("Error! " + msg)

    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(ip + "【发现漏洞】")  # 相当于调用了my_slot
            time.sleep(0.01)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MyWindow()
    w.show()
    app.exec()

在这里插入图片描述
模拟,正在检查 192.168.1.105 上的漏洞…
模拟,正在检查 192.168.1.106 上的漏洞…
模拟,正在检查 192.168.1.107 上的漏洞…
模拟,正在检查 192.168.1.108 上的漏洞…
模拟,正在检查 192.168.1.109 上的漏洞…
Error! 192.168.1.109【发现漏洞】

案例2

除了接收Qt自带的信号之外,我们也可以自行定义信号,在合适的时机,自行发射信号
自定义信号需要使用到 pyqtSignal来声明信号 ,并且需要在类中的函数之外声明
如果会自定义信号,那么信号和槽基本上也就掌握了。否则永远只会接收别人发射出的信号

import sys
import time

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

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

    def __init__(self):
        super().__init__()
        self.init_ui()
        self.msg_history = []  # 用于存放消息

    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))  # 把列表中的元素用<br>连接成一个字符串
        self.msg.resize(440, self.msg.frameSize().height() + 15)  # 手动调整msg的高度,加一行的高度
        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
            self.my_signal.emit(msg)  # 相当于调用了my_slot
            if i % 5 == 3:
                # 表示发射信号 对象.信号.发射(参数)
                self.my_signal.emit(ip + "【发现漏洞】")  # 相当于调用了my_slot
            time.sleep(0.01)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MyWindow()
    w.show()
    app.exec()

在这里插入图片描述

Qt designer

安装

https://build-system.fman.io/qt-designer-download

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

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ui = uic.loadUi(r"C:\Users\hipeson\Desktop\大论文\mini_sys.ui")  # 加载ui文件
    # 展示窗口
    ui.show()
    app.exec()

在这里插入图片描述

控件添加信号与槽

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


class MyWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.ui = None  # 添加一个ui属性
        self.init_ui()

    def init_ui(self):
        self.ui = uic.loadUi("./logging.ui")
        # print(self.ui.__dict__)  # 最顶层对象的所有属性,以(key:value方式显示)
        self.user_name = self.ui.lineEdit  # 用户名输入框
        self.password_name = self.ui.lineEdit_2  # 密码输入框
        login_btn = self.ui.pushButton  # 登录按钮
        forget_btn = self.ui.pushButton_2  # 忘记密码按钮
        text_browser = self.ui.textBrowser  # 文本显示区域

        # 给登录按钮被点击绑定槽函数
        login_btn.clicked.connect(self.login)

    def login(self):
        print("正在登陆...")
        # 提取用户名、密码
        print(self.user_name.text())
        print(self.password_name.text())


if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MyWindow()
    # 展示窗口
    w.ui.show()
    app.exec()

在这里插入图片描述

案例三

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


class MyWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.ui = None  # 添加一个ui属性
        self.init_ui()

    def init_ui(self):
        self.ui = uic.loadUi("./logging.ui")
        # print(self.ui.__dict__)  # 最顶层对象的所有属性,以(key:value方式显示)
        # 提取要操作的控件
        self.user_name = self.ui.lineEdit  # 用户名输入框
        self.password_name = self.ui.lineEdit_2  # 密码输入框
        self.login_btn = self.ui.pushButton  # 登录按钮
        self.forget_btn = self.ui.pushButton_2  # 忘记密码按钮
        self.text_browser = self.ui.textBrowser  # 文本显示区域

        # 给登录按钮被点击绑定槽函数
        self.login_btn.clicked.connect(self.login)

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


if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MyWindow()
    # 展示窗口
    w.ui.show()
    app.exec()

单线程改成多线程

可以很明显的看到,程序是卡顿的

why?为什么会卡顿呢?大名鼎鼎的Qt不止于此吧!

答:只要是带界面的程序,一般来说程序运行后会用当前线程进行事件的检查、按钮等图形界面的更新操作,如果在执行某个逻辑代码(例如登录)时耗时非常验证,此时就会出现界面卡顿

怎样做更好?

答:我们一般将界面的显示用主线程来操作,逻辑功能代码或者耗时操作的代码都用另外线程进行处理

这也就是为什么要研究PyQt中的多线程了,因为它能实现多任务,让界面用一个线程更新,让逻辑代码在另外一个线程中,互不影响
在这里插入图片描述

import sys

from PyQt5.QtCore import QThread
from PyQt5.QtWidgets import *
from PyQt5 import uic
import time


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

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


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

    def init_ui(self):
        self.ui = uic.loadUi("./thread.ui")
        # 从ui文件中加载控件
        line_edit = 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()  # 开始线程 run方法执行


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

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值