一. 前言
一直在为 Python 寻求一个桌面端的框架 ,对于 PyQT5 之前也有一定的研究 ,但是不太符合期望。
最近发现 PyQT6 已经发布很长一段时间了 ,但是国内文档偏少, 所以决定自己体验一下效果。
本文目的 :
- 记录 Python PyQT6 的快速上手流程 ,以及使用方式
二. PyQT6 使用案例
2.1 基础入门
入门代码是从 ChatGPT 上面抄的案例 ,我们很简单就能实现一个窗口功能 :
- S1 : 安装 PyQT6 的依赖 --
pip install PyQt6
- S2 : 代码中引入 PyQT6 的
相关对象依赖
- S3 : 创建一个 QApplication 对象 ,用于承载整个应用
- S4 : 丰富布局和功能
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout, QMessageBox
class MyApp(QWidget):
def __init__(self):
super().__init__()
# 设置窗口标题
self.setWindowTitle('PyQt6 Demo')
# 创建一个按钮
self.button = QPushButton('点击一下', self)
self.button.clicked.connect(self.show_message)
# 设置布局
layout = QVBoxLayout()
layout.addWidget(self.button)
self.setLayout(layout)
def show_message(self):
# 显示消息框
QMessageBox.information(self, 'Message', 'Hello, PyQt6!')
if __name__ == '__main__':
app = QApplication(sys.argv)
# 创建 MyApp 实例
my_app = MyApp()
my_app.resize(300, 200) # 设置窗口大小
my_app.show() # 显示窗口
sys.exit(app.exec())
2.2 稍微复杂一下
入门很简单, 但是生产应用上不会有这么简单的功能 ,在这篇里面会简单演示以下功能 :
- 更复杂的页面体系 ,包括 Tab 页 ,子项 ,控制台等各种功能组件
- 更好看的界面样式 : 整体的风格,流程的切换 ,布局等
- 应用发布 : 打包成可执行的应用进行发布
2.3 功能点一 : 页面体系
PyQT 中有着丰富的组件 ,可以帮助我们实现各种功能
组件 | 描述 |
---|---|
QApplication | 应用程序的入口点,处理事件循环和初始化。 |
QWidget | 所有用户界面对象的基类,是空白的 GUI 容器。 |
QMainWindow | 一个主窗口控件,支持菜单栏、工具栏、状态栏等标准窗口功能。 |
QDialog | 对话框窗口,用于短期任务或用户输入。 |
QPushButton | 按钮控件,用户可以点击它来触发动作。 |
QLabel | 文本或图像标签,用于显示只读信息。 |
QLineEdit | 单行文本输入控件,用户可以输入和编辑文本。 |
QTextEdit | 多行文本编辑器,支持富文本格式。 |
QComboBox | 下拉列表控件,允许用户从多个选项中选择。 |
QCheckBox | 复选框控件,允许用户选择或取消选择一个选项。 |
QRadioButton | 单选按钮控件,用户可以从一组互斥的选项中选择一个。 |
QListView | 列表视图控件,用于显示和操作项目列表。 |
QTreeView | 树形视图控件,用于显示和操作层次结构数据。 |
QTableView | 表格视图控件,用于显示二维数据。 |
QVBoxLayout | 垂直布局管理器,用于垂直排列控件。 |
QHBoxLayout | 水平布局管理器,用于水平排列控件。 |
QGridLayout | 网格布局管理器,用于创建行和列的控件布局。 |
QFormLayout | 表单布局管理器,用于以标签-控件对的形式排列控件。 |
QMessageBox | 消息框控件,用于显示信息、警告或错误对话框。 |
QFileDialog | 文件对话框,用于打开、保存文件或选择目录。 |
QColorDialog | 颜色对话框,用于选择颜色。 |
QFontDialog | 字体对话框,用于选择字体。 |
QProgressBar | 进度条控件,用于显示任务的进度。 |
QSlider | 滑动条控件,用于选择范围内的数值。 |
QSpinBox | 旋转框控件,用于选择数值(带步进按钮)。 |
QTimer | 定时器对象,用于触发定时事件。 |
QCanvas | 绘图区域,用于自定义图形的绘制。 |
QMenuBar | 菜单栏控件,用于创建和管理应用程序菜单。 |
QStatusBar | 状态栏控件,用于显示应用程序的状态信息。 |
@ QtWidgets — PyQt Documentation v6.7.1 (riverbankcomputing.com)
更复杂的功能可以参考官方文档 ,这里就不细说了 👉👉👉
2.4 功能点二 : 更复杂的界面样式
- 方式一 : 直接通过代码实现界面的编排
- 方式二 : 通过
QT Design
帮助我们实现界面的编排
毕竟还是新手 ,方式二对我而言上手过于困难 ,功能不复杂,我这里直接用代码画界面。
2.5 功能点三 : 部署执行文件
- S1 : 安装依赖 - pip install pyinstaller
- S2 : 执行打包命令 - pyinstaller --onefile --windowed --name MyApp main.py
- S3 : 修改后执行 - pyinstaller MyApp.spec
# -*- mode: python ; coding: utf-8 -*-
a = Analysis( ['main.py','data_menu.py','layout_sidebar.py','layout_table.py','data_table.py','data_menu.py'],
pathex=['D:\\code\python\\PythonDemoGit\\pythonDemoGit\\gui_pyqt6'],
binaries=[],
datas=[('styles.qss','.')],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
optimize=0,
)
// .... 略
暂时还不知道有没有不改 spec 文件
, 一次性打包成功的方式- datas 注意格式 ,否则也会打包失败
- 最后文件如下图所示 ,运行即可
三. 实现一个简单的爬虫客户端
下面开始实现一个简单的爬虫客户端 ,作用就是从掘金抓取文章标题和链接,并且保存在本地 :
3.1 数据爬取
- S1 : 安装依赖 - pip install requests beautifulsoup4
- S2 : 先抓取专栏列表 ,再抓起专栏下的文章列表
专栏列表抓取
import requests
from bs4 import BeautifulSoup
def search_list(url):
# 发送 HTTP 请求获取页面内容
response = requests.get(url)
# 检查请求是否成功
if response.status_code != 200:
print(f"调用接口异常:")
return []
# 解析页面内容
soup = BeautifulSoup(response.text, 'html.parser')
# 假设详情项在 <a> 标签内,并且包含标题和链接
details = []
# 通过 CSS 选择器抓取数据
for a_tag in soup.select('.column-link'):
# 获取 title
title = "默认名称"
for element in a_tag:
for title_item in element.select(".title"):
title = title_item.get_text().strip()
# 获取地址
link = a_tag['href']
# 如果链接是相对路径,转换为绝对路径
if not link.startswith('http'):
link = requests.compat.urljoin(url, link)
details.append({'title': title, 'link': link})
return details
文章列表抓起
import requests
from bs4 import BeautifulSoup
def generate_data(url):
# 发送 HTTP 请求获取页面内容
response = requests.get(url)
# 检查请求是否成功
if response.status_code != 200:
print(f"调用接口异常:")
return []
# 解析页面内容
soup = BeautifulSoup(response.text, 'html.parser')
# 假设详情项在 <a> 标签内,并且包含标题和链接
details = []
# 通过 CSS 选择器抓取数据
for content_list in soup.select('.content-main'):
# 获取 title
title = "默认名称"
link = ""
for title_item in content_list.select(".title"):
title = title_item.get_text().strip()
link = title_item['href']
if not link.startswith('http'):
link = requests.compat.urljoin(url, link)
details.append({'title': title, 'link': link})
return details
3.2 关键操作节点
包括3个节点 :
左边的侧边栏
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QPushButton
from data_menu import search_list
from PyQt6.QtCore import pyqtSignal
class Sidebar(QWidget):
# 定义一个信号,将生成的数据传递出去
data_generated = pyqtSignal(str)
def __init__(self, parent=None):
super().__init__(parent)
detail_list = search_list(
"https://juejin.cn/user/3790771822007822/columns")
sidebar_layout = QVBoxLayout()
self.setLayout(sidebar_layout)
for detail in detail_list:
button = QPushButton(detail['title'])
button.setProperty("url", detail['link'])
# 为 button 绑定事件
button.clicked.connect(self.on_button_clicked)
sidebar_layout.addWidget(button)
sidebar_layout.addStretch()
def on_button_clicked(self):
button = self.sender() # 获取发送信号的按钮
url = button.property("url")
self.data_generated.emit(url)
右边的文章列表
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QTableWidget, QTableWidgetItem
from data_table import generate_data
class TableWithPagination(QWidget):
def __init__(self, data, rows_per_page=10, parent=None):
super().__init__(parent)
self.table = QTableWidget()
self.table.setRowCount(rows_per_page)
self.table.setColumnCount(3)
self.table.setHorizontalHeaderLabels(["文章名称", "文章路径"])
self.current_page = 0
self.rows_per_page = rows_per_page
self.total_data = data
# 右侧布局
right_layout = QVBoxLayout()
right_layout.addWidget(self.table)
self.setLayout(right_layout)
def update_table(self, url):
print("拿到url地址:", url)
self.table.clearContents()
data_list = generate_data(url)
for row, data_detail in enumerate(data_list):
print("查询到对象", row, data_detail)
self.table.setItem(row, 0, QTableWidgetItem(data_detail['title']))
self.table.setItem(row, 1, QTableWidgetItem(data_detail['link']))
以及最核心的入口函数
import sys
import os
from PyQt6.QtWidgets import QApplication, QMainWindow, QWidget, QHBoxLayout
from layout_sidebar import Sidebar
from layout_table import TableWithPagination
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("PyQt Modular Example")
self.resize(800, 600)
# 右侧表单和分页控制
data = []
self.table_info = TableWithPagination(data)
# 左侧侧边栏
self.sidebar = Sidebar()
# 主布局
main_layout = QHBoxLayout()
main_layout.addWidget(self.sidebar)
main_layout.addWidget(self.table_info)
# 设置结构
container = QWidget()
container.setLayout(main_layout)
self.setCentralWidget(container)
# 连接信号与槽函数
self.sidebar.data_generated.connect(self.table_info.update_table)
# 加载样式表
stylesheet_path = os.path.join(os.path.dirname(__file__), 'styles.qss')
self.load_stylesheet(stylesheet_path)
def load_stylesheet(self, filename):
"""加载并应用样式表"""
with open(filename, "r", encoding="utf-8") as file:
self.setStyleSheet(file.read())
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
3.3 基础效果展示
- 这个插件仅仅进行了简单的优化 ,
总的来说可视化效果还不错
卡顿较为明显
,主要是在互联网调用延迟
上面- 初始化布局未自适应 ,体验感一般 ,
需要花时间优化样式
针对这些问题 ,我们下一篇着重优化一下展示的效果
3.4 源码已上传 gitee
- 后续的 Python 代码都会陆续提交上去,欢迎 star❤️❤️
总结
文章内容不复杂, 只是把 PyQT6 学习过程中的核心关键点和内容梳理了出来 ,便于后续业务中开箱即用。
关于这个系列后续还会有计划 ,但是作为子分支 ,更新时间不定 ,欢迎关注。
总结一下 :
- 入门难度 : 上手不难 , Python 本地人半天足够 ,外地人1-2天。复杂场景要花一些时间。
- 用法 : 和 Java 或者其他后端语言写前端界面的方式类似, 样式和前端的 CSS 类似
- 场景 : 能覆盖绝大多数场景
最后的最后 ❤️❤️❤️👇👇👇
- 👈 欢迎关注 ,超200篇优质文章,未来持续高质量输出 🎉🎉
- 🔥🔥🔥 系列文章集合,高并发,源码应有尽有 👍👍
- 走过路过不要错过 ,知识无价还不收钱 ❗❗