上位机开发---PyQt5

一、PyQt简介&环境搭建

1. PyQt简介

PyQt是一套Python的GUI开发框架,即图形用户界面开发框架.

Python中经常使用的GUI控件集有PyQt、Tkinter、wxPython、Kivy、PyGUI和Libavg

其中PyQt是Qt(c++语言实现的)为Python专门提供的扩展

1.1 Qt

Qt 是一个1991年由Qt Company开发的跨平台C++图形用户界面开发框架。
2008年,Qt Company被诺基亚公司收购,Qt也因此成为诺基亚旗下的编程语言工具。
2012年,Qt被Digia收购。
2014年4月,跨平台集成开发环境Qt Creator 3.1.0正式发布

1.2 PyQt

  • 基础高性能的Qt的图形界面控件集
  • 能够跨平台运行在windows、linux和macos等系统上
  • 使用信号/槽(signal/slot)机制进行通信(其它语言采用回调方式)
  • 对Qt库的完全封装

1.3 通过pip安装PyQt5

  • pip install PyQt5 安装PyQt5
  • pip install PyQt5-tools 安装Qt工具软件
  • pip install PyQt5-stubs 安装PyQt5语法检测包(可选)

如果安装缓慢,请配置pip源:

pip config set global.index-url https://mirror.baidu.com/pypi/simple 

 二、PyQt创建窗口

1. 第一个PyQt窗口

from PyQt5.QtWidgets import QApplication,QWidget
import sys

# 1.创建应用程序
app = QApplication(sys.argv)

# 2.创建窗口
w = QWidget()

# 3.显示窗口
w.show()

# 4.等待窗口停止
sys.exit(app.exec())

执行代码,就会显示PyQt5窗口:

2. PyQt模块简介

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

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

3. 窗口标题和图标

应用程序图标是一个小的图像,通常在标题栏的左上角显示。

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

# 1.创建应用程序
app = QApplication(sys.argv)

# 2.创建窗口
w = QWidget()

# 设置窗口标题
w.setWindowTitle('窗口')
# 设置窗口尺寸
w.resize(400, 300)
# 设置图标
w.setWindowIcon(QIcon('qq.png'))

w.setToolTip('这个一个气泡提示')

# 3.显示窗口
w.show()

# 4.等待窗口停止
sys.exit(app.exec())

三、PyQt文本和图片

1. 文本控件

文本控件是QLabel

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

# 1.创建应用程序
app = QApplication(sys.argv)

# 2.创建窗口
w = QWidget()

# 修改窗口标题
w.setWindowTitle('文本展示')


label = QLabel()
label.setText('第一个文本')
# 将文本控件添加到窗口中
label.setParent(w)

# 3.显示窗口
w.show()

# 4.等待窗口停止
sys.exit(app.exec())

2. 图片控件

QLabel 控件既可以显示文本,也可以显示图片

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


def init_widget(w: QWidget):
    # 修改窗口标题
    w.setWindowTitle('图片展示')
    # 展示图片 
    label = QLabel()
    pixmap = QPixmap('img.png')
    label.setPixmap(pixmap)
    # 显示到窗口中
    label.setParent(w)
    # 改变窗口大小
    w.resize(pixmap.width(), pixmap.height())


if __name__ == '__main__':
    # 1.创建应用程序
    app = QApplication(sys.argv)

    # 2.创建窗口
    w = QWidget()
    init_widget(w)

    # 3.显示窗口
    w.show()

    # 4.等待窗口停止
    sys.exit(app.exec())

 四、PyQt输入框

1. 单行文本输入框

QLineEdit控件可以输入单行文本

from PyQt5.QtWidgets import QApplication, QWidget, QLineEdit, QVBoxLayout
from PyQt5.QtCore import *
from PyQt5.QtGui import QIcon
import sys


def init_widget(w: QWidget):
    # 修改窗口标题
    w.setWindowTitle('单行输入框')
    # 设置窗口大小
    w.resize(480, 320)

    layout = QVBoxLayout()
    # 展示单行输入框
    edit = QLineEdit()
    # 设置输入框提示
    edit.setPlaceholderText('请输入用户名')
    # 设置文本
    edit.setText('张三')
    # 获取单选框的文字
    text = edit.text()
    print(text)
    # 设置输入框最大字符数
    edit.setMaxLength(10)
    layout.addWidget(edit)

    edit3 = QLineEdit("Password")
    edit3.setPlaceholderText('请输入密码')
    edit3.setEchoMode(QLineEdit.Password)
    layout.addWidget(edit3)

    w.setLayout(layout)


if __name__ == '__main__':
    # 1.创建应用程序
    app = QApplication(sys.argv)
    # 2.创建窗口
    w = QWidget()
    init_widget(w)
    # 3.显示窗口
    w.show()
    # 4.等待窗口停止
    sys.exit(app.exec())

QLineEdit的方法

方法

说明

setEchoMode()

QLineEdit.Normal正常显示所输入的字符,默认选项

QLineEdit.NoEcho不显示任何输入的字符,常用于密码类型的输入,且其密码长度需要保密时

QLineEdit.Password显示与平台相关的密码掩码字符,而不是实际输入的字符

QLineEdit.PasswordEchoOnEdit在编辑时显示字符,负责显示密码类型的输入

setPlaceholderText()

设置文本框浮显文字

setText()

设置文本框内容

setMaxLength()

设置文本框所允许输入的最大字符数

2. 多行文本输入框 

QTextEdit控件用来输入多行文本

from PyQt5.QtWidgets import QApplication,QWidget,QTextEdit
from PyQt5.QtCore import *
from PyQt5.QtGui import QIcon
import sys

# 1.创建应用程序
app = QApplication(sys.argv)

# 2.创建窗口
w = QWidget()


# 修改窗口标题
w.setWindowTitle('多行输入框')
# 多行输入框 
edit = QTextEdit()

# 设置提示内容
edit.setPlaceholderText('请输入发表的内容')
# 设置文本内容
edit.setPlainText('武汉疫情')
# 获取输入的内容
print(edit.toPlainText())
edit.clear()

# 显示多行输入框
edit.setParent(w)

# 3.显示窗口
w.show()

# 4.等待窗口停止
sys.exit(app.exec())

QTextEdit的方法

方法

说明

setPlainText()

设置多行文本框的文本内容

toPlainText()

返回多行文本框的文本内容

setHtml()

设置多行文本框的内容为HTML文档

toHtml()

返回多行文本框的HTML文档内容

clear()

清空多行文本框的内容

 五、PyQt按钮

常见的按钮实现类包括:QPushButtonQRadioButtonQCheckBox

QPushButton是最普通的按钮控件,可以响应一些用户的事件

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


def func():
    print("按下按钮啦,火箭发射!")


# 1.创建应用程序
app = QApplication(sys.argv)

# 2.创建窗口
w = QWidget()

# 修改窗口标题
w.setWindowTitle('普通按钮')
#  显示普通按钮 
btn = QPushButton()
# 添加按钮提示
btn.setText('发射')
# 给按钮添加点击事件
btn.clicked.connect(func)
# 展示按钮
btn.setParent(w)

# 3.显示窗口
w.show()

# 4.等待窗口停止
sys.exit(app.exec())

六、PyQt信号和槽

1. 信号和槽简介

信号和槽机制是 QT 的核心机制,应用于对象之间的通信

  • 信号和槽是用来在对象间传递数据的方法
  • 当一个特定事件发生的时候,signal会被emit出来,slot调用是用来响应相应的signal
  • Qt中对象已经包含了许多预定义的 signal(基本组件都有各自特有的预定义的信号)
  • 槽函数绑定了信号,信号一旦发出,就会自动调用绑定的槽函数

2. 信号和槽绑定

通过调用 QObject 对象的 connect 函数来将对象的信号与另外一个对象的槽函数相关联,当发射者发射信号时,接收者的槽函数将被调用

点击按钮,输出hello

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


# 槽函数
def click():
    print('hello1')


# 1.创建应用程序
app = QApplication(sys.argv)

# 2.创建窗口
w = QWidget()

# 修改窗口标题
w.setWindowTitle('信号和槽的绑定')
# 添加按钮
btn = QPushButton()
btn.setText('点我')
btn.setParent(w)

# 绑定按钮点击的信号和处理的槽函数
# 方式1:槽函数使用函数
# clicked 信号
# click定义的槽函数
btn.clicked.connect(click)
# 方式2:槽函数使用lambda表达式
# 信号和槽函数参数必须要保持一致
# 如果信号中参数有=   槽函数可以不用添加
btn.clicked.connect(lambda: print('hello2'))

# 3.显示窗口
w.show()

# 4.等待窗口停止
sys.exit(app.exec())

3. 使用PyQt的槽函数

利用系统自带退出函数QApplication.quit点击按钮,关闭窗口

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import QIcon
import sys

# 1.创建应用程序
app = QApplication(sys.argv)

# 2.创建窗口
w = QWidget()

# 修改窗口标题
w.setWindowTitle('使用系统的槽函数')
# 创建按钮 
btn = QPushButton()
btn.setText('关闭窗口')
# 显示按钮
btn.setParent(w)

# 信号和槽绑定 
btn.clicked.connect(QApplication.quit)  # 使用QApplication的quit方法

# 3.显示窗口
w.show()

# 4.等待窗口停止
sys.exit(app.exec())

七、PyQt布局layout 

1. 水平布局QHBoxLayout

from PyQt5.QtWidgets import QApplication,QWidget,QPushButton,QHBoxLayout
from PyQt5.QtCore import *
from PyQt5.QtGui import QIcon
import sys

# 1.创建应用程序
app = QApplication(sys.argv)

# 2.创建窗口
w = QWidget()

# 修改窗口标题
w.setWindowTitle('水平布局')
"""------------------ 创建按钮 ------------------"""
btn1 = QPushButton('1')
btn2 = QPushButton('2')
btn3 = QPushButton('3')
btn4 = QPushButton('4')
btn5 = QPushButton('5')
# 创建布局
layout = QHBoxLayout()
# 添加布局到窗口中
w.setLayout(layout)
# 按钮控件添加到布局中
layout.addWidget(btn1)
layout.addWidget(btn2)
layout.addWidget(btn3)
layout.addWidget(btn4)
layout.addWidget(btn5)


# 3.显示窗口
w.show()

# 4.等待窗口停止
sys.exit(app.exec())

2. 竖直布局QVBoxLayout

from PyQt5.QtWidgets import QApplication,QWidget,QPushButton,QVBoxLayout
from PyQt5.QtCore import *
from PyQt5.QtGui import QIcon
import sys

# 1.创建应用程序
app = QApplication(sys.argv)

# 2.创建窗口
w = QWidget()

# 修改窗口标题
w.setWindowTitle('竖直布局')
w.resize(480, 240)
"""------------------ 创建并添加5个按钮 ------------------"""
# 创建布局
layout = QVBoxLayout()
# 布局添加到窗口中
w.setLayout(layout)

# 控件添加到布局中
layout.addWidget(QPushButton('1'))
layout.addWidget(QPushButton('2'))
layout.addWidget(QPushButton('3'))
layout.addWidget(QPushButton('4'))
layout.addWidget(QPushButton('5'))

# 3.显示窗口
w.show()

# 4.等待窗口停止
sys.exit(app.exec())

3. 表单布局QFormLayout

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


def func():
    name = nameEdit.text()
    age = ageEdit.text()
    phone = phoneEdit.text()
    print("姓名:{} 年龄:{} 电话:{}".format(name, age, phone))


# 1.创建应用程序
app = QApplication(sys.argv)

# 2.创建窗口
w = QWidget()
# w.resize(480, 320)

# 修改窗口标题
w.setWindowTitle('表单布局')
"""------------------ 创建布局 ------------------"""
layout = QFormLayout()
# 添加到窗口中
w.setLayout(layout)

# 输入框
nameEdit = QLineEdit()
ageEdit = QLineEdit()
phoneEdit = QLineEdit()
btn = QPushButton('发送')
# 信号和槽绑定
btn.clicked.connect(func)

# 添加到布局中
layout.addRow('姓名', nameEdit)
layout.addRow('年纪', ageEdit)
layout.addRow('电话', phoneEdit)
layout.addRow('', btn)


# 3.显示窗口
w.show()

# 4.等待窗口停止
sys.exit(app.exec())

4. 布局嵌套

通过布局嵌套可以实现更加复杂的布局

from PyQt5.QtWidgets import QApplication,QWidget,QPushButton,QHBoxLayout,QVBoxLayout,QFormLayout
from PyQt5.QtCore import *
from PyQt5.QtGui import QIcon
import sys

# 1.创建应用程序
app = QApplication(sys.argv)

# 2.创建窗口
w = QWidget()


# 修改窗口标题
w.setWindowTitle('嵌套布局')

"""------------------ 实现布局 ------------------"""
# 整体水平布局
wholeLayout = QHBoxLayout()
# 添加整体布局
w.setLayout(wholeLayout)

# 每一部分布局
layout1 = QHBoxLayout()
layout2 = QVBoxLayout()
layout3 = QVBoxLayout()

# 添加到整体的布局中
wholeLayout.addLayout(layout1)
wholeLayout.addLayout(layout2)
wholeLayout.addLayout(layout3)

# 控件
# 添加第一部分控件
layout1.addWidget(QPushButton('1'))
layout1.addWidget(QPushButton('2'))
# 添加第二部分控件
layout2.addWidget(QPushButton('3'))
layout2.addWidget(QPushButton('4'))
# 添加第三部分控件
layout3.addWidget(QPushButton('5'))
layout3.addWidget(QPushButton('6'))
layout3.addWidget(QPushButton('7'))
# 3.显示窗口
w.show()

# 4.等待窗口停止
sys.exit(app.exec())

八、PyQt单选框和复选框

1. 单选框

QRadioButton是单选按钮,它提供了一组可供选择的按钮和文本标签,用户可以选择其中一个选项

单选框选中的信号是:toggled

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


def func(checked):
    '''
    状态变化的槽函数
    :param checked: 是否被选中
    :return:
    '''
    print('状态变化', checked)


# 1.创建应用程序
app = QApplication(sys.argv)

# 2.创建窗口
w = QWidget()

# 修改窗口标题
w.setWindowTitle('单选框')
"""------------------ 创建布局 ------------------"""
layout = QHBoxLayout()
# 添加布局到窗口中
w.setLayout(layout)
# 创建两个单选框
rb1 = QRadioButton('男')
rb2 = QRadioButton('女')
rb1.setChecked(True)
# 添加到布局中
layout.addWidget(rb1)
layout.addWidget(rb2)

# 绑定信号和槽
rb1.toggled.connect(func)

# 3.显示窗口
w.show()

# 4.等待窗口停止
sys.exit(app.exec())

2. 复选框

QCheckBox提供了一组带文本标签的复选框,用户可以选择多个选项

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys


def func(state):
    # 判断是否选中
    if state == Qt.Checked: # 2
        print('选中')
    else:                   # 0
        print('未选中')


# 1.创建应用程序
app = QApplication(sys.argv)

# 2.创建窗口
w = QWidget()

# 修改窗口标题
w.setWindowTitle('复选框')
"""------------------ 窗口布局 ------------------"""
layout = QHBoxLayout()
# 添加到窗口中
w.setLayout(layout)

# 控件
label = QLabel()
label.setText('谦哥的爱好:')
ck1 = QCheckBox('抽烟')
ck2 = QCheckBox('喝酒')
ck3 = QCheckBox('烫头')

# 选中第一个
ck1.setChecked(True)

# 添加控件到布局中
layout.addWidget(label)
layout.addWidget(ck1)
layout.addWidget(ck2)
layout.addWidget(ck3)

# 绑定信号和槽
ck1.stateChanged.connect(func)

# 3.显示窗口
w.show()

# 4.等待窗口停止
sys.exit(app.exec())

九、PyQt对话框

对话框是为了更好地实现人与程序的交互
对话框主要是完成特定场景下的功能,比如删除确认等

QDialog的子类有QMessageBoxQFileDialogQFontDialogQInputDialog

1. QMessageBox

QMessageBox是普通的对话框

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import QIcon
import sys


def deleteUser():
    # 弹出对话框,让用户确认
    result = QMessageBox.question(w, '提示', '确认要删除好朋友吗?', 
                                  QMessageBox.Ok | QMessageBox.Cancel, 
                                  QMessageBox.Cancel)
    if result == QMessageBox.Ok:
        print('确认删除')
    elif result == QMessageBox.Cancel:
        print('取消删除')


# 1.创建应用程序
app = QApplication(sys.argv)

# 2.创建窗口
w = QWidget()

# 修改窗口标题
w.setWindowTitle('对话框')
"""------------------ 创建按钮 ------------------"""
btn = QPushButton('删除用户')
# 显示控件
btn.setParent(w)

# 信号和槽绑定
btn.clicked.connect(deleteUser)

# 3.显示窗口
w.show()

# 4.等待窗口停止
sys.exit(app.exec())

2. QIputDialog

QIputDialog是输入对话框,由一个文本框和两个按钮(OK按钮和Cancel按钮)组成

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import QIcon
import sys

def func():
    str,success = QInputDialog.getText(w,'提示','请输入角色名称')
    if success:
        edit.setText(str)


# 1.创建应用程序
app = QApplication(sys.argv)

# 2.创建窗口
w = QWidget()


# 修改窗口标题
w.setWindowTitle('输入提示框')
"""------------------ 创建界面 ------------------"""
layout = QHBoxLayout()
# 添加布局
w.setLayout(layout)

# 控件
btn = QPushButton('创建角色')
edit = QLineEdit()
# 控件添加到布局中
layout.addWidget(btn)
layout.addWidget(edit)

# 信号和槽函数绑定
btn.clicked.connect(func)

# 3.显示窗口
w.show()

# 4.等待窗口停止
sys.exit(app.exec())

十、PyQt面向对象

Qt窗口继承

写一个自定义类继承QWidget

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys


class MyWindow(QWidget):

    def __init__(self, title):
        super().__init__()
        self.setWindowTitle(title)


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

    window = MyWindow("窗口标题")
    window.show()

    sys.exit(app.exec_())

通过继承QWidget来实现窗体

在构造中,必须调用super函数,否则将出行错误

初始化ui

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys


class MyWindow(QWidget):

    def __init__(self, title):
        super().__init__()
        self.setWindowTitle(title)
        self.init_ui()

    def init_ui(self):
        layout = QHBoxLayout()
    	# ---------------------------------

        # 在这里初始化界面内容
        
    	# ---------------------------------
        self.setLayout(layout)


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

    window = MyWindow("窗口标题")
    window.show()

    sys.exit(app.exec_())

十一、PyQt自定义信号和槽

1. 为什么要使用信号和槽

使用信号和槽的好处在于,可以将代码分离成更小的、更可重用的部分,从而提高代码的可读性和可维护性。这种机制使得不同的对象之间可以进行通信,而不需要它们之间直接相互调用方法。

如果直接调用函数,会导致代码的紧密耦合,不利于代码的维护和扩展。此外,使用信号和槽也可以方便地实现多线程编程,因为它们可以在不同的线程之间进行通信。

使用信号和槽的目的:

  • 用于代码之间的解耦合
  • 子线程通知主线程更新界面

2. 在文件内部定义信号和槽

PyQt中自定义信号和槽的步骤如下:

  1. 定义信号:在类中定义一个信号,使用PyQt的信号机制可以实现自定义信号。可以通过pyqtSignal()方法来创建一个信号对象。pyqtSignal参数槽函数的参数类型
  2. 定义槽:在类中定义一个槽函数,使用@pyqtSlot()装饰器将该方法注册为槽函数。
  3. 连接信号和槽:使用信号.connect(槽函数)方法将信号和槽连接起来。
  4. 触发信号:在需要触发信号的地方,使用信号.emit()方法来触发该信号,参数和槽函数参数一致。
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject

class MyObject(QObject):
    # a. 定义一个自定义信号
    my_signal = pyqtSignal(str)

    # b. 定义一个槽函数
    @pyqtSlot(str)
    def my_slot(self, message):
        print("Received message: ", message)

# 创建一个对象
obj = MyObject()

# b. 连接信号和槽 
obj.my_signal.connect(obj.my_slot)

# c. 触发信号
obj.my_signal.emit("Hello, World!")

首先定义了一个名为my_signal的自定义信号。然后,我们定义了一个名为my_slot的槽函数,并使用@pyqtSlot()装饰器将其注册为槽函数。最后,我们创建了一个MyObject对象,并将my_signal信号连接到my_slot槽函数。最后,我们通过调用emit()方法来触发该信号,并将消息传递给槽函数。 

3. 在不同文件定义信号和槽

当在不同的类中连接信号和槽时,需要使用QObject.connect()方法来建立连接。假设我们有两个类SenderReceiver,其中Sender类定义了一个信号my_signalReceiver类定义了一个槽函数my_slot,那么连接过程如下:

from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot

class Sender(QObject):
    my_signal = pyqtSignal(str)

    def send_data(self):
        data = "Hello, World!"
        self.my_signal.emit(data)

class Receiver(QObject):
    @pyqtSlot(str)
    def my_slot(self, data):
        print("Received data: ", data)

sender = Sender()
receiver = Receiver()

# 将信号连接到槽
sender.my_signal.connect(receiver.my_slot)

# 触发信号
sender.send_data()

创建了两个类SenderReceiver,并分别实例化了它们的对象senderreceiver。然后,我们使用connect()方法将Sender类中的信号my_signal连接到了Receiver类中的槽函数my_slot。最后,我们通过调用send_data()方法来触发信号,从而使得槽函数被调用,并输出接收到的数据。

  • 30
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值