PyQT5介绍及基本使用

王江

<a id="PyQt5_1"></a>PyQt5 <h3><a id="1_PyQt5_3"></a>1. PyQt5的下载与安装</h3></br> <a id="11_PyQt5_5"></a>1.1 PyQt5介绍 <h3>Qt(官方发音 [kju:t])是一个跨平台的C++开发库,主要用来开发图形用户界面(Graphical User Interface,GUI)程序</h3></br> <h3>Qt 是纯 C++ 开发的,正常情况下需要先学习C语言、然后在学习C++然后才能使用Qt开发带界面的程序</h3></br> <h3>多亏了开源社区使得<strong>Qt 还可以用Python、Ruby、Perl 等脚本语言进行开发。</strong></h3></br> <h3><strong>Qt 支持的操作系统有很多,例如通用操作系统 Windows、Linux、Unix,智能手机系统Android、iOS, 嵌入式系统等等</strong>。可以说是跨平台的</h3></br> <h3>QT官网:https://doc.qt.io/qt-5/index.html</h3></br> <h3>PyQt的开发者是英国的“Riverbank Computing”公司。它提供了GPL(简单的说,以GPL协议发布到网上的素材,你可以使用,也可以更改,但是经过你更改然后再次发布的素材必须也遵守GPL协议,主要要求是必须开源,而且不能删减原作者的声明信息等)与商业协议两种授权方式,因此它可以免费地用于自由软件的开发。</h3></br> <h3><strong>PyQt可以运行于Microsoft Windows、Mac OS X、Linux以及Unix的多数变种上</strong>。</h3></br> <h3>PyQt是Python语言的GUI(Graphical User Interface,简称 GUI,又称图形用户接口)编程解决方案之一</h3></br> <h3>可以用来代替Python内置的Tkinter。其它替代者还有PyGTK、wxPython等,与Qt一样,PyQt是一个自由软件</h3></br> <h3>文档相关地址:https://www.riverbankcomputing.com/software/pyqt/</h3></br> <h3>比较不错的参考资料:https://wiki.python.org/moin/PyQt/Tutorials</h3></br> <h3>Qt (C++ 语言 GUI )</h3></br> <h3>PyQt = Python + Qt技术</h3></br> <h3>Tkinter</h3></br> <h3>Python官方采用的标准库,优点是作为Python标准库、稳定、发布程序较小,缺点是控件相对较少。</h3></br> <h3>wxPython</h3></br> <h3>基于wxWidgets的Python库,优点是控件比较丰富,缺点是稳定性相对差点、文档少、用户少。</h3></br> <h3>PySide2、PyQt5</h3></br> <h3>基于Qt 的Python库,优点是控件比较丰富、跨平台体验好、文档完善、用户多。</h3></br> <h3>缺点是 库比较大,发布出来的程序比较大。</h3></br> <h3>PyQt5 的开发者是英国的“Riverbank Computing”公司 , 而 PySide2 则是 qt 针对python语言提供的专门</h3></br> <a id="12_windows_PyQt5_49"></a>1.2 windows PyQt5的安装 执行命令,允许创建虚拟环境 pip install virtualenv pip install virtualenvwrapper-win 创建新的虚拟环境 mkvirtualenv -p python3 py3-qt --no-download 安装pyqt5(命令行) workon py3-qt pip install pyqt5 -i https://pypi.tuna.tsinghua.edu.cn/simple <h3> 版本测试 from PyQt5 import QtWidgets from PyQt5.QtCore import * print(QT_VERSION_STR) <h3> pip加速国内镜像 阿里云 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/ <h3><a id="2PyQt5UI_103"></a>2.PyQt5基本UI</h3></br> <a id="21_PyQt_105"></a>2.1 第一个PyQt程序 import sys from PyQt5.QtWidgets import QApplication, QWidget if __name__ == '__main__': app = QApplication(sys.argv) w = QWidget() w.setWindowTitle("第一个PyQt") w.show() app.exec() <h3> <a id="23__142"></a>2.3 模块介绍 <h3>PyQt中有非常多的功能模块,开发中最常用的功能模块主要有三个:</h3></br> <strong>QtCore</strong>:包含了核心的非GUI的功能。主要和时间、文件与文件夹、各种数据、流、URLs、mime类文件、进程与线程一起使用<strong>QtGui</strong>:包含了窗口系统、事件处理、2D图像、基本绘画、字体和文字类<strong>QtWidgets</strong>:包含了一些列创建桌面应用的UI元素 <h3>可以参考PyQt官网的所有模块,地址:https://www.riverbankcomputing.com/static/Docs/PyQt5/module_index.html#ref-module-index</h3></br> <h3>C++具体实现的API文档,地址:https://doc.qt.io/qt-5/qtwidgets-module.html</h3></br> <h3><strong>用到什么功能就它相关的api或者别人分享的使用心得,这是学习最快的方式</strong></h3></br> <h3><a id="3UI_156"></a>3.基本UI</h3></br> <h3>窗口内的所有控件,若想在窗口中显示,都需要表示它的父亲是谁,而不能直接使用 show 函数显示</h3></br> <a id="31_QPushButton_160"></a>3.1 按钮QPushButton import sys from PyQt5.QtWidgets import QApplication, QWidget, QPushButton if __name__ == '__main__': app = QApplication(sys.argv) w = QWidget() w.setWindowTitle("第一个PyQt程序") btn = QPush("按钮") btn.setParent(w) w.show() app.exec() <h3> <a id="32_QLabel_191"></a>3.2 文本QLabel <h3>纯文本控件名称为 QLabel , 位于 PyQt5.QtWidgets 里面</h3></br> <h3>纯文本控件仅仅作为标识显示而已,类似输入内容前的一段标签提示(账号 、密码)</h3></br> import sys from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel if __name__ == '__main__': app = QApplication(sys.argv) w = QWidget() w.setWindowTitle("第一个PyQt") label = QLabel("账号: ", w) label.setGeometry(20, 20, 30, 30) w.show() app.exec() <h3> import sys from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel if __name__ == '__main__': app = QApplication(sys.argv) w = QWidget() w.setWindowTitle("第一个PyQt") label = QLabel("账号: ", w) label.setGeometry(20, 20, 30, 30) w.show() app.exec() <h3> <a id="33__263"></a>3.3 输入框 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 = QPush("注册", w) btn.setGeometry(50, 80, 70, 30) w.show() app.exec() <a id="34__300"></a>3.4 调整窗口大小 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) label.setGeometry(20, 20, 30, 20) edit = QLineEdit(w) edit.setPlaceholderText("请输入账号") edit.setGeometry(55, 20, 200, 20) btn = QPush("注册", w) btn.setGeometry(50, 80, 70, 30) w.show() app.exec() <a id="35__335"></a>3.5 调整窗口显示屏幕中间 move:移动屏幕 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) center = QDesktopWidget().availableGeometry().center() print("center:",center) x = center.x() y = center.y() 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) label.setGeometry(20, 20, 30, 20) edit = QLineEdit(w) edit.setPlaceholderText("请输入账号") edit.setGeometry(55, 20, 200, 20) btn = QPush("注册", w) btn.setGeometry(50, 80, 70, 30) w.show() app.exec() <h3> <a id="36_icon_393"></a>3.6 设置窗口icon <h3><a href="https://www.easyicon.net/" rel="nofollow">可下载icon网址</a></h3></br> import sys from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QApplication, QWidget if __name__ == '__main__': app = QApplication(sys.argv) w = QWidget() w.setWindowTitle("看看我图标帅吗") w.setWindowIcon(QIcon('test.jpg')) w.show() app.exec() <h3> <h3><a id="4_421"></a>4.布局</h3></br> <h3>在Qt里面布局分为四个大类 :</h3></br> QBoxLayoutQGridLayoutQFormLayoutQStackedLayout <a id="41_QBoxLayout_430"></a>4.1 QBoxLayout <h3>直译为:盒子布局</h3></br> <h3>一般使用它的两个子类QHBoxLayout 和 QVBoxLayout 负责水平和垂直布局</h3></br> <a id="411__436"></a>4.1.1 垂直布局 import sys from PyQt5.QtWidgets import QApplication, QVBoxLayout, QWidget, QPushButton, QGroupBox, QMainWindow from PyQt5.QtCore import Qt class My(QWidget): def __init__(self): super().__init__() self.resize(300, 300) self.setWindowTitle("垂直布局") layout = QVBoxLayout() layout.addStretch(1) btn1 = QPush("按钮1") layout.addWidget(btn1) layout.addStretch(1) btn2 = QPush("按钮2") layout.addWidget(btn2) layout.addStretch(1) btn3 = QPush("按钮3") layout.addWidget(btn3) layout.addStretch(2) btn4 = QPush("按钮4") layout.addWidget(btn4) layout.addStretch(2) self.setLayout(layout) if __name__ == '__main__': app = QApplication(sys.argv) w = My() w.show() app.exec() <h3> <a id="412__502"></a>4.1.2 水平布局 import sys from PyQt5.QtWidgets import QApplication, QWidget, QGroupBox, QVBoxLayout, QHBoxLayout, QRadioButton class My(QWidget): def __init__(self): super().__init__() self.init_ui() def init_ui(self): container = QVBoxLayout() hobby_box = QGroupBox("爱好") v_layout = QVBoxLayout() btn1 = QRadio("抽烟") btn2 = QRadio("喝酒") btn3 = QRadio("烫头") v_layout.addWidget(btn1) v_layout.addWidget(btn2) v_layout.addWidget(btn3) hobby_box.setLayout(v_layout) gender_box = QGroupBox("性别") h_layout = QHBoxLayout() btn4 = QRadio("男") btn5 = QRadio("女") h_layout.addWidget(btn4) h_layout.addWidget(btn5) gender_box.setLayout(h_layout) container.addWidget(hobby_box) container.addWidget(gender_box) music_box = QGroupBox("音乐") m_layout = QHBoxLayout() btn6 = QRadio("古风") btn7 = QRadio("流行") 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 = My() w.show() app.exec() <h3> <a id="42_QGridLayout_587"></a>4.2 QGridLayout <a id="_589"></a>网格布局 import sys from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QLineEdit, QGridLayout class My(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", "*", "&lt;-"], 3: ["0", ".", "=", "/", "C"] } layout = QVBoxLayout() edit = QLineEdit() edit.setPlaceholderText("请输入内容") layout.addWidget(edit) grid = QGridLayout() for line_number, line_data in data.items(): for col_number, number in enumerate(line_data): btn = QPush(number) grid.addWidget(btn, line_number, col_number) layout.addLayout(grid) self.setLayout(layout) if __name__ == '__main__': app = QApplication(sys.argv) w = My() w.show() app.exec() <h3> <a id="43_QFormLayout_647"></a>4.3 QFormLayout <h3>一般适用于提交数据<strong>form表单</strong>。比如: 登录,注册类似的场景</h3></br> import sys from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QVBoxLayout, QFormLayout, QLineEdit, QPushButton, QApplication, QWidget class My(QWidget): def __init__(self): super().__init__() self.init_ui() def init_ui(self): self.setFixedSize(300, 150) container = QVBoxLayout() form_layout = QFormLayout() edit = QLineEdit() edit.setPlaceholderText("请输入账号") form_layout.addRow("账号:", edit) edit2 = QLineEdit() edit2.setPlaceholderText("请输入密码") form_layout.addRow("密码:", edit2) container.addLayout(form_layout) login_btn = QPush("登录") login_btn.setFixedSize(100, 30) container.addWidget(login_btn, alignment=Qt.AlignRight) self.setLayout(container) if __name__ == '__main__': app = QApplication(sys.argv) w = My() w.show() app.exec() <h3> <a id="44__712"></a>4.4 抽屉布局 <h3>提供了多页面切换的布局,一次只能看到一个界面。 <strong>抽屉布局</strong></h3></br> 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 My(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() win1 = Window1() win2 = Window2() self.stacked_layout.addWidget(win1) self.stacked_layout.addWidget(win2) def init_ui(self): self.setFixedSize(300, 270) container = QVBoxLayout() widget = QWidget() widget.setLayout(self.stacked_layout) widget.setStyleSheet("background-color:grey;") btn_press1 = QPush("抽屉1") btn_press2 = QPush("抽屉2") btn_press1.clicked.connect(self.btn_press1_clicked) btn_press2.clicked.connect(self.btn_press2_clicked) container.addWidget(widget) container.addWidget(btn_press1) container.addWidget(btn_press2) self.setLayout(container) def btn_press1_clicked(self): self.stacked_layout.setCurrentIndex(0) def btn_press2_clicked(self): self.stacked_layout.setCurrentIndex(1) if __name__ == "__main__": app = QApplication(sys.argv) win = My() win.show() app.exec() <h3> <h3><a id="5__799"></a>5. 窗口</h3></br> <a id="51__801"></a>5.1 分类 <h3>在Qt中,生成窗口有三种方式: QWidget | QMainWindow | QDialog</h3></br> QWidget <h3>控件和窗口的父类 ,自由度高(什么都东西都没有),没有划分菜单、工具栏、状态栏、主窗口 等区域</h3></br> QMainWindow <h3>是 QWidget的子类,包含菜单栏,工具栏,状态栏,标题栏等,中间部分则为主窗口区域</h3></br> QDialog <h3>对话框窗口的基类</h3></br> <a id="52_QWidget_817"></a>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() <h3> <a id="52_QMainWindow_852"></a>5.2 QMainWindow import sys from PyQt5.QtWidgets import QMainWindow, QLabel, QApplication class My(QMainWindow): def __init__(self): super().__init__() self.init_ui() def init_ui(self): label = QLabel("这是文字~~") label.setStyleSheet("font-size:30px;color:red") menu = self.menuBar() 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 = My() w.setWindowTitle("我是窗口标题....") w.show() app.exec() <h3> <a id="53_QDialog_906"></a>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 = QPush("确定", self) ok_btn.setGeometry(50, 50, 100, 30) if __name__ == '__main__': app = QApplication(sys.argv) w = MyDialog() w.setWindowTitle("对话框") w.show() app.exec() <h3> <h3><a id="6__941"></a>6. 信号与槽</h3></br> <a id="61__943"></a>6.1 信号与槽介绍 <h3>一、说明<br></br> 信号和槽是 Qt的核心内容</h3></br> 信号(signal)<br></br> 其实就是事件(按钮点击 、内容发生改变 、窗口的关闭事件) 或者是 状态 (check选中了, togglebutton 切换。) <h3>当程序触发了某种状态或者发生了某种事件(比如:按钮被点击了, 内容改变等等),那么即可发射出来一个信号。</h3></br> <h3>槽( slot)<br></br> 若想捕获这个信号,然后执行相应的逻辑代码,那么就需要使用到槽 , 槽实际上是一个函数, 当信号发射出来后,会执行与之绑定的槽函数</h3></br> <h3>将信号与槽链接<br></br> 为了能够实现,当点击某个按钮时执行某个逻辑,需要把具体的信号和具体的槽函数绑定到一起.</h3></br> <h3>操作大体流程如下</h3></br> 对象.信号.connect(槽函数) <h3> 当出现了某一种信号(某一种事件)的时候,我们需要执行一段代码(用函数来包装这份代码。) <h3>解决办法</h3></br> 信号和槽 <a id="62__977"></a>6.2 案例 <h3>功能:接收信号</h3></br> import sys from PyQt5.QtWidgets import QApplication, QWidget, QPushButton class My(QWidget): def __init__(self): super().__init__() self.init_ui() def init_ui(self): self.resize(500, 300) btn = QPush("点我点我", 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 = My() w.show() app.exec() <h3> <a id="63__1021"></a>6.3 自定义信号 <h3>除了接收Qt自带的信号之外,我们也可以自行定义信号,在合适的时机,自行发射信号</h3></br> <h3>自定义信号需要使用到 pyqtSignal来声明信号 ,并且需要在类中的函数之外声明</h3></br> <h3>如果会自定义信号,那么信号和槽基本上也就掌握了。否则永远只会接收别人发射出的信号</h3></br> import sys import time from PyQt5.QtWidgets import * from PyQt5.QtCore import * class My(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) 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 = QPush("开始检测", self) btn.clicked.connect(self.check) h_layout.addStretch(1) h_layout.addWidget(btn) h_layout.addStretch(1) 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.(msg) self.msg.setText("&lt;br&gt;".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 if i % 5 == 3: self.my_signal.emit(msg + "【发现漏洞】") time.sleep(0.01) if __name__ == '__main__': app = QApplication(sys.argv) w = My() w.show() app.exec() <h3> <h3><a id="7Qt_Designer_1117"></a>7.Qt Designer</h3></br> <a id="71__1119"></a>7.1 介绍 <h3>纯靠代码来编写界面,效率属实是有点底,今天我们用另外一个辅助设计图形化的软件 QT Designer</h3></br> <a id="72__1123"></a>7.2 下载 <h3>Mac版本:[http://download.codetutor.top/software/Mac/Qt%20Designer.dmg](http://download.codetutor.top/software/Mac/Qt Designer.dmg)</h3></br> <h3>Windows版本:[http://download.codetutor.top/software/win/Qt%20Designer%20Setup.exe](http://download.codetutor.top/software/win/Qt Designer Setup.exe)</h3></br> <a id="73__1129"></a>7.3 安装&amp;运行 <h3>安装过程很简单,按照正常软件安装即可,安装后的图片如下图:</h3></br> <h3> <h3><strong>但Mac平台用户要注意,运行时会出现如下图问题</strong>:</h3></br> <h3> <h3><strong>解决办法</strong>:在“应用程序”文件夹,按住control键然后运行。只需要这种方式运行第一次即可,以后运行就像普通软件一样打开</h3></br> <h3> <a id="74_QT_Designer_1143"></a>7.4 使用QT Designer <h3>Mac运行之后的效果如下:</h3></br> <h3> <a id="75__1149"></a>7.5 使用流程 <h3>1.创建一个基于QWidget的界面</h3></br> <h3> <h3>2.此时会创建一个新的窗口,如下效果</h3></br> <h3> <h3>3.拖动想要的控件</h3></br> <h3> <h3>4.选中控件,看属性</h3></br> <h3> <h3>5.修改属性</h3></br> <h3> <h3>6.如果没有看到preperty等窗口怎么办?看下图</h3></br> <h3> <h3>7.信号与槽(没有没有看到Singal/Slot Editor请按照上一步操作进行显示)</h3></br> <h3> <h3>8.预览效果</h3></br> <h3> <h3>9.保存</h3></br> <h3> <h3>10.python代码使用test.ui文件</h3></br> <h3>若要加载ui文件,则需要导入 uic 模块 , 它位于PyQt5 中</h3></br> """ 动态加载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() <h3> <h3><a href="https://doc.itprojects.cn/0001.zhishi/python.0008.pyqt5rumen/index.html#/README" rel="nofollow">参考资料</a></h3></br> <h3><a href="https://www.itprojects.cn/" rel="nofollow">www.itprojects.cn</a></h3></br> <a href="https://blog.csdn.net/weixin_42917352/article/details/131257796" >查看原文</a> 原文转载自blog.csdn.net,著作权归作者所有