一. PyQt5介绍

1. PyQt5 是什么?

PyQt5 是 Python 对 Qt5 库的完整封装。Qt 是一个跨平台的 C++ GUI 框架,PyQt 让你能用 Python 调用 Qt 的功能,快速构建桌面应用。

核心特点:

  • 跨平台:Windows、macOS、Linux

  • 功能丰富:GUI、绘图、数据库、网络、多线程等

  • 面向对象:与 Python 风格完美契合

  • 两种许可:GPL(开源免费)和商业许可

2. 基本架构理解

主要模块:

PyQt5.QtWidgets     # 窗口控件(最常用)
PyQt5.QtCore        # 核心功能(信号槽、事件等)
PyQt5.QtGui         # 图形界面组件
PyQt5.QtMultimedia  # 多媒体
PyQt5.QtWebEngine   # 网页引擎

3. 各部分模块介绍

(1)窗口

        1. QWidget

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

        2. QMainWindow

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

        3. QDialog

对话框窗口的基类

基本使用
if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = QWidget()
    # 设置窗口标题
    w.setWindowTitle("第一个PyQt")
    # 展示窗口
    w.show()

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

文字说明:

  • 只要是 Qt 制作的 app,必须有且只有 1 个QApplication对象

  • sys.argv当做参数的目的是将运行时的命令参数传递给QApplication对象

  • 创建了一个QWidget对象,将它的标题设置为 “第一个 PyQt”

  • 然后调用show方法显示出来

  • 程序开始运行程序,直到关闭了窗口

QWidget窗口调整(其实是通用的,这些方法控件啥的也都能用,后面也会有演示)
w.resize(w, h) # 设置窗口的w, h

w.move(x, y) # 设置窗口的x, y

w.frameGeometry().getRect() # 获取当前窗口的x, y, w, h

w.setWindowIcon(QIcon('xxx.png')) # 设置图标,QIcon是QTGui里的

w.setLayout(xxx) # 设置布局

w.setStyleSheet("background-color:grey;") # 设置样式

QMainWindow 窗口调整

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("剪切")

(2)控件

        按钮
from PyQt5.QtWidgets import QPushButton

btn = QPushButton("btn")

btn.setParent(xxx) # 里头填QWidget对象或者其他
        标签
from PyQt5.QtWidgets import QLabel

text = QLabel("btn", xxx) # 就等于之前的创建加设置父亲,只是两步合为一步,分开写也行 

text.setGeometry(x, y, w, h) # 设置位置与大小,其他控件也可以

text.setStyleSheet("background-color:grey;") # 设置样式

text.resize(x, y) # 设置大小

text.setWordWrap(True) # 自动换行

text.setAlignment(Qt.AlignTop) # 靠上

text.repaint() # 更新内容
        输入框
edit = QLineEdit(w)
edit.setPlaceholderText("please input ... ")
edit.setGeometry(x, y, w, h)
        滚动条
scroll = QScrollArea()
scrollsetWidget(xxx)

(3)布局

  • QBoxLayout
  • QGridLayout
  • QFormLayout
  • QStackedLayout
        1、QBoxLayout
                QVBoxLayout(垂直布局)
layout = QVBoxLayout # 创建布局器

w.setLayout(layout) # 使用布局器

对于之前让控件显示都是设置父对象,现在可以直接 layout.addWidget(btn) 就达到了相同效果

layout.addStretch(2) # 添加一个伸缩器(理解成弹簧,和加的位置有关,这个参数就是一个比例关系,就理解成弹簧系数)
                QHBoxLayout(水平布局)

                        同垂直布局

        2、QGridLayout(网格布局/九宫格布局)
grid = QGridLayout()
grid.addwidget(btn, line_num, col_num) # 添加哪个控件,添加到第几行第几个
        3、QFormLayout(form表单)
        4、QStackedLayout(抽屉布局)
每个抽屉都用QWidget新建,而后再用addWidget加入抽屉布局
随后可以用setCurrentInder(0)来选择显示哪个Widget,0代表加入的第一个
        5、分组
hobby = QGroupBox("爱好") 
hobby.setLayout(xxx)

# 可以创建一个组,组里再设置布局,同时组也可以放入别人的布局器
# 比如实现下图这种结构,hobby是垂直,gender是水平,
# 最后再把他两调用setLayout都放入一个垂直布局器

(4)信号和槽

        概念

                1. 信号 (signal)
        其实就是事件(按钮点击、内容发生改变、窗口的关闭事件)或者是状态(check 选中了,togglebutton 切换。)当程序触发了某种状态或者发生了某种事件(比如:按钮被点击了,内容改变等等),那么即可发射出来一个信号。
                2. 槽 (slot)
        若想捕获这个信号,然后执行相应的逻辑代码,那么就需要使用到槽,槽实际上是一个函数,当信号发射出来后,会执行与之绑定的槽函数。
                3. 将信号与槽链接
        为了能够实现,当点击某个按钮时执行某个逻辑,需要把具体的信号和具体的槽函数绑定到一起。

        使用
对象.信号.connect(槽函数)  # 绑定槽函数

对象.信号.emit(参数) # 发射信号

pyqtSignal(str) # 自定义信号,(str)表示接收一个参数,类型是str

二. 案例

案例介绍:有一个标签显示id和标签所在的坐标,三个按钮分别对应三个功能:按下后id+1,按下后id-1,用0显示id有几位(如12345就显示00000),同时还要完成标签可拖动,拖动的同时显示的坐标也要求事实变化

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

id = 123
label = None

def incr_id():
    global id, label
    id += 1
    update_label()
    label.repaint()

def decre_id():
    global id, label
    id -= 1
    update_label()
    label.repaint()

def showZero():
    global id, label
    num = len(str(id)) if id != 0 else 1
    print("0的个数为:" + "0"*num)
    from PyQt5.QtWidgets import QMessageBox
    QMessageBox.information(None, "0的个数", "0"*num)

def update_label():
    global id, label
    label.setText(f"{id} postion: {label.x()} , {label.y()}")

class DraggableLable(QLabel):
    def __init__(self, text, parent):
        super().init__(text, parent)
        self.setMouseTracking(True)
        self.offset = None
        self.setStyleSheet("border: 2px solid red; padding: 5px;")

    def mousePressEvent(self, ev):
        if ev.button() == Qt.LeftButton:
            self.offset = ev.pos()
        super().mousePressEvent(ev)

    def mouseMoveEvent(self, ev):
        if ev.buttons() & Qt.LeftButton and self.offset is not None:
            new_pos = self.parent().mapFromGlobal(ev.globalPos()) - self.offset
            self.move(new_pos)
            self.setText(str(id) + " position:" + str(self.x()) + " , " + str(self.y()))
         super().mouseMoveEvent(ev)

    def mouseReleaseEvent(self, ev):
        if ev.button() == Qt.LeftButton:
            self.offset = None
        super().mouseReleaseEvent(ev)

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

    w = QWidget()

    contain = QVBoxLayout()
    hlayout = QHBoxLayout()

    w.setWindowTitle("PyQt5 Test")

    label = DragableLable(str(id) + " positon: 226 , 100", w)
    label.setGeometry(226, 100, 300, 60)
    
    btn_group = QGroupBox("按钮")
    btn1 = QPushButton("Btn1")
    btn1.clicked.connect(incr_id)
    btn1.setStyleSheet("border: 2px solid red; padding: 5px;")
    hlayout.addWidget(btn1)

    btn2 = QPushButton("Btn2")
    btn2.clicked.connect(decre_id)
    btn2.setStyleSheet("border: 2px solid red; padding: 5px;")
    hlayout.addWidget(btn2)

    btn3 = QPushButton("Btn3")
    btn3.clicked.connect(showZero)
    btn3.setStyleSheet("border: 2px solid red; padding: 5px;")
    hlayout.addWidget(btn3)

    btn_group.setLayout(hlayout)

    contain.addStretch(3)
    contain.addWidget(btn_group)
    contain.addStretch(1)
    w.resize(700, 450)
    w.move(2000, 600)
    w.setLayout(contain)

    w.show()

    app.exec_()

说明

1、可拖拽类继承要自定义类,继承QLabel,重写三个方法

2、整体是垂直布局,按钮采用水平布局,就是说QWidget中是垂直布局,垂直布局中有个标签还有个水平布局,水平布局中有三个按钮

3、通过往垂直布局中加入addStretch可以讲按钮控制在下半部分,根据我的代码来说,按钮上面占全部大小的三份,下面站全部大小的一份,也就是3:1,按钮在从下往上的四分之一处

4、按钮信号是clicked,不再需要显示的emit发送信号,因为内部已经做了

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐