Introduction and basic use of PyQT5

PyQt5

1. Download and installation of PyQt5

1.1 Introduction to PyQt5

Qt (official pronunciation [kju:t]) is a cross-platform C++ development library, mainly used to develop Graphical User Interface (GUI) programs

Qt is developed purely in C++. Under normal circumstances, you need to learn C language first, then learn C++ before you can use Qt to develop programs with interfaces.

Thanks to the open source community, Qt can also be developed with scripting languages ​​such as Python, Ruby, and Perl.

Qt supports many operating systems, such as general operating systems Windows, Linux, and Unix, smartphone systems Android, iOS, embedded systems, and so on . It can be said to be cross-platform

QT official website: https://doc.qt.io/qt-5/index.html

The developer of PyQt is the British company "Riverbank Computing". It provides GPL (simply put, you can use or change the materials published online under the GPL agreement, but the materials you change and then re-release must also comply with the GPL agreement. The main requirement is that it must be open source and cannot be deleted. (minus the original author's statement information, etc.) and commercial agreement, so it can be used for free software development.

PyQt runs on Microsoft Windows, Mac OS X, Linux, and most variants of Unix .

PyQt is one of the GUI (Graphical User Interface, GUI for short, also known as graphical user interface) programming solutions in the Python language

Can be used instead of Python's built-in ones Tkinter. Other alternatives include PyGTK, wxPythonetc., like Qt, PyQt is a free software

Document related address: https://www.riverbankcomputing.com/software/pyqt/

A good reference material: https://wiki.python.org/moin/PyQt/Tutorials

  • Qt (C++ language GUI)

  • PyQt = Python + Qt technology

  • Tkinter

    The standard library officially adopted by Python has the advantage of being a Python standard library, stable, and smaller release program. The disadvantage is that there are relatively few controls.

  • wxPython

    The Python library based on wxWidgets has the advantage of rich controls, but the disadvantages are relatively poor stability, few documents, and few users.

  • PySide2、PyQt5

    The Python library based on Qt has the advantages of rich controls, good cross-platform experience, complete documentation, and many users.

    The disadvantage is that the library is relatively large and the published program is relatively large.

    The developer of PyQt5 is the British company "Riverbank Computing", while PySide2 is a specialized tool provided by Qt for the Python language.

1.2 Windows PyQt5 installation

  1. Execute the command to allow the creation of a virtual environment
pip install virtualenv
pip install virtualenvwrapper-win
  1. Create a new virtual environment
mkvirtualenv -p python3 py3-qt --no-download
  1. Install pyqt5 (command line)
workon py3-qt  #切换到py3-qt环境
pip install pyqt5 -i https://pypi.tuna.tsinghua.edu.cn/simple

image-20230515225937502

  1. Version testing
# 如果执行成功,没有任何错误提示,则表明环境搭建成功
from PyQt5 import QtWidgets

# 当然也可以查看PyQt版本
from PyQt5.QtCore import *


print(QT_VERSION_STR)

image-20230515230526200

  • pip accelerates domestic mirroring
阿里云  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/

2.PyQt5 basic UI

2.1 The first PyQt program

import sys

from PyQt5.QtWidgets import QApplication, QWidget # 1.导入模块

if __name__ == '__main__':
    # 2.创建一个 QApplication 对象,指向QApplication ,接受命令行参数

    app = QApplication(sys.argv)
    #  3. 创建一个  QWidget对象
    w = QWidget()

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

    # 5. 展示窗口
    w.show()

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

image-20230515230700956

2.2 argv

import sys

print(sys.argv)

image-20230515231412243

2.3 Module introduction

There are many functional modules in PyQt. There are three main functional modules that are most commonly used in development:

  • QtCore : Contains core non-GUI functionality. Mainly used with time, files and folders, various data, streams, URLs, mime class files, processes and threads
  • QtGui : includes window system, event handling, 2D images, basic painting, fonts and text classes
  • QtWidgets : Contains a series of UI elements for creating desktop applications

You can refer to all modules on the PyQt official website, address: https://www.riverbankcomputing.com/static/Docs/PyQt5/module_index.html#ref-module-index

C++ specific implementation API documentation, address: https://doc.qt.io/qt-5/qtwidgets-module.html

Which function is used depends on its related API or the usage experience shared by others. This is the fastest way to learn.

3.Basic UI

If all controls in the window want to be displayed in the window, they need to indicate who their father is, and cannot be displayed directly using the show function.

3.1 Button QPushButton

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

image-20230515231855120

3.2 Text QLabel

The name of the plain text control is QLabel, located PyQt5.QtWidgetsinside

The plain text control is only displayed as a logo, similar to a label prompt (account number, password) before input content.

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

image-20230515232214756

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

image-20230515232244255

3.3 Input box

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)
    # x,y,w,h
    btn.setGeometry(50, 80, 70, 30)

    # 展示窗口
    w.show()

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

3.4 Adjust window size

  • resize
import sys

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

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = QWidget()
    # 设置窗口标题
    w.setWindowTitle("第一个PyQt5程序")

    # 窗口的大小
    w.resize(500,500)
    # 纯文本
    label = QLabel("账号", w)
    # 设置位置x,y,w,h
    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()

3.5 Adjust the window display to the middle of the screen

  • move: move the screen
import sys

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

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = QWidget()
    # 设置窗口标题
    w.setWindowTitle("第一个PyQt5程序")

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

    # 调整到左上角
    # w.move(0,0)

    # 获取屏幕中心点
    center = QDesktopWidget().availableGeometry().center()
    print("center:",center)
    x = center.x()
    y = center.y()
    # print(x/2,y/2)
    w.move(x//2,y//2)
    # 纯文本

    print(w.frameSize())
    print(w.frameGeometry())
    print(w.frameGeometry().getRect())

    # 居中显示
    old_x,old_y,width,height = w.frameGeometry().getRect()
    w.move(x-width//2,y-height//2)


    label = QLabel("账号", w)
    # 设置位置x,y,w,h
    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()

image-20230519234729204

3.6 Set window icon

Downloadable icon URL

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('test.jpg'))
    # 显示QWidget
    w.show()

    app.exec()

image-20230519235041396

4.Layout

Layouts in Qt are divided into four major categories:

  • QBoxLayout
  • QGridLayout
  • QFormLayout
  • QStackedLayout

4.1 QBoxLayout

Literal translation: box layout

Generally use its two subclasses QHBoxLayoutand QVBoxLayoutare responsible for horizontal and vertical layout

4.1.1 Vertical layout

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 : 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)

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

        layout.addStretch(2)

        self.setLayout(layout)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    # 创建一个QWidget子类
    w = MyWindow()
    w.show()
    app.exec()

image-20230520000242070

4.1.2 Horizontal 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)


        # 音乐标签
        music_box = QGroupBox("音乐")
        m_layout = QHBoxLayout()

        btn6 = QRadioButton("古风")
        btn7 = QRadioButton("流行")

        m_layout.addWidget(btn6)
        m_layout.addWidget(btn7)

        music_box.setLayout(m_layout)


        container.addWidget(music_box)




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


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

    w = MyWindow()
    w.show()

    app.exec()

image-20230526230756063

4.2 QGridLayout

grid layout

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


class MyWindow(QWidget):

    def __init__(self):
        super().__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):
                # 此时col_number是第几列,number是要显示的符号
                btn = QPushButton(number)
                # grid.addWidget(btn)
                grid.addWidget(btn, line_number, col_number)

        # 把网格布局追加到容器中
        layout.addLayout(grid)

        self.setLayout(layout)


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

    w = MyWindow()
    w.show()

    app.exec()

image-20230526231843507

4.3 QFormLayout

Generally suitable for submitting data form forms . For example: login, registration similar scenarios

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

image-20230526232028808

4.4 Drawer layout

A multi-page switching layout is provided, and only one interface can be seen at a time. drawer layout

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


class Window1(QWidget):
    def __init__(self):
        super().__init__()
        QLabel("我辈岂是蓬蒿人", self)
        self.setStyleSheet("background-color:green;")


class Window2(QWidget):
    def __init__(self):
        super().__init__()
        QLabel("人生得以须尽欢", 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()

image-20230526232309149

5. Window

5.1 Classification

In Qt, there are three ways to generate a window: QWidget| QMainWindow|QDialog

  1. QWidget

The parent class of controls and windows, with a high degree of freedom (nothing), and no division of menus, toolbars, status bars, main windows, etc.

  1. QMainWindow

Yes QWidgetsubclass, including menu bar, toolbar, status bar, title bar, etc. The middle part is the main window area

  1. QDialog

Base class for dialog windows

5.2 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()

image-20230526232850921

5.2 QMainWindow

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

image-20230526233306456

5.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()

image-20230526233352946

6. Signals and Slots

6.1 Introduction to signals and slots

1. Description
Signals and slots are the core content of Qt

  1. A signal
    is actually an event (button click, content change, window closing event) or state (check is selected, togglebutton switches.)

When the program triggers a certain state or a certain event occurs (for example: the button is clicked, the content changes, etc.), then a signal can be emitted.

  1. If you want to capture this signal
    and then execute the corresponding logic code, you need to use the slot. The slot is actually a function. When the signal is emitted, the slot function bound to it will be executed.

  2. Link signals and slots
    In order to implement a certain logic when a button is clicked, specific signals and specific slot functions need to be bound together.

The general operation process is as follows

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

img

当出现了某一种信号(某一种事件)的时候,我们需要执行一段代码(用函数来包装这份代码。)

Solution

信号和槽

6.2 Case

Function: receive signal

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

image-20230526234343799

6.3 Custom signals

In addition to receiving the signals that come with Qt, we can also define our own signals and emit signals at the right time.

Custom signals need to be pyqtSignalused declare the signal, and they need to be declared outside the functions in the class

If you can customize signals, you can basically master signals and slots. Otherwise, you will always receive signals sent by others.

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.AlignCenter)  # 靠上
        self.msg.setStyleSheet("background-color: yellow; color: red;")

        # 创建一个滚动对象
        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()

image-20230526235615971

7.Qt Designer

7.1 Introduction

The efficiency of writing interfaces purely by code is really low. Today we use another graphical software to assist in design.QT Designer

7.2 Download

Mac version: [http://download.codetutor.top/software/Mac/Qt%20Designer.dmg](http://download.codetutor.top/software/Mac/Qt Designer.dmg)

Windows version: [http://download.codetutor.top/software/win/Qt%20Designer%20Setup.exe](http://download.codetutor.top/software/win/Qt Designer Setup.exe)

7.3 Installation & Operation

The installation process is very simple, just follow the normal software installation. The picture after installation is as follows:

image-20201123214407351

However, Mac platform users should pay attention to the following problems when running :

img

Workaround : In the Applications folder, hold down controlthe key and then run. You only need to run it this way for the first time, and then open it just like ordinary software.

image-20201123214951153

7.4 Using QT Designer

The effect after running on Mac is as follows:

image-20201123215209758

7.5 Usage process

1. Create an interface based on QWidget

image-20201123215321248

2. A new window will be created at this time, with the following effect

image-20201123215359517

3. Drag the desired control

image-20201123215551661

4. Select the control and look at the properties

image-20201123215750887

5. Modify attributes

image-20201123215829602

6. What should I do if I don’t see the property and other windows? Look at the picture below

image-20201123220059274

7. Signals and slots (if you don’t see the Singal/Slot Editor, please follow the previous step to display it)

image-20201123220951729

8. Preview effect

image-20201123221137373

9.Save

image-20201123221409036

10.Python code usage test.uifiles

To load the ui file, you need to import uicthe module, which is located PyQt5in

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

import sys

from PyQt5.QtWidgets import QApplication
from PyQt5 import uic

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

    ui = uic.loadUi("./test.ui")
    # 展示窗口
    ui.show()

    app.exec()

image-20201123221857466

References

www.itprojects.cn

Guess you like

Origin blog.csdn.net/weixin_42917352/article/details/131257796