news 2026/5/16 16:23:23

在PySide6/PyQt6的项目中封装一些基础类库,包括文件对话框、字体对话框、颜色对话框、消息对话框等内容

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
在PySide6/PyQt6的项目中封装一些基础类库,包括文件对话框、字体对话框、颜色对话框、消息对话框等内容

在我们实际开发项目的时候,有时候为了使用方便,会针对一些常用到的内容进行一定的封装处理,以降低使用的难度和减少相关代码,本篇随笔介绍在PySide6/PyQt6的项目中封装一些基础类库,包括文件对话框、字体对话框、颜色对话框、消息对话框等内容。

1、常用对话框处理封装的优点

对常用对话框的调用(包括文件对话框、字体对话框、颜色对话框、消息对话框等内容),可能调用的时候,会遇到一些问题,如对于常用的文件目录对话框,可能会出现下面一些问题:

  • 参数顺序难记

  • 单选 / 多选 / 保存 / 目录 API 不统一

  • 最近路径不好维护

  • 每个窗口都写一遍

如果对它进行一定的封装,可以实现更多可选参数的设置以及更好的支持:

✅ 打开单文件
✅ 打开多文件
✅ 保存文件
✅ 选择目录
✅ 文件过滤器常量
✅ 最近目录记忆(进程级 / 可扩展到配置)
✅ Windows / macOS / Linux 兼容

如果对这些对话框进行辅助类的统一封装,会具有以下是一些主要的优点:

1)代码复用

封装常用对话框可以避免重复代码。你可以定义一个统一的函数或类来处理所有常用对话框操作,从而在多个地方复用这段代码。

2)一致性

通过封装,你可以确保所有常用对话框的外观和行为一致。这有助于提高用户体验,使用户在应用程序中获得统一的交互方式。

3)简化调用

封装可以简化调用过程。你可以将常用的参数设置(如标题、图标、按钮类型等)预先定义好,从而在调用时减少参数输入。

4)易于维护

当需要更改对话框的行为或样式时,只需在封装函数中进行修改,而不必在应用程序中的每个调用点进行更改。这使得维护变得更加简单和高效。

5)增强可读性

通过使用封装的函数或类,代码变得更易读。其他开发者可以一眼看出对话框的作用,而不必深入了解其具体实现。

6)集中管理

封装有助于集中管理对话框的逻辑,比如处理用户输入、响应用户选择等。这样可以更方便地进行逻辑更新或错误处理。

7)扩展性

如果将来需要增加新的对话框或修改现有对话框的逻辑,封装使得扩展更加容易。你可以在封装的基础上进行扩展,而不影响现有的代码结构。

2、文件对话框的封装

如果我们对文件对话框进行封装,那么需要考虑打开、保存文件对话框等常规操作,而文件的格式有多种多样,我们为了方便,可以提供更细节的函数选择具体的文件,如文本文件、Excel文件等。

classFileDialogUtil:"""文件、目录对话框工具类"""#定义文件过滤器all_filter ="All File (*.*);;*.*"word_filter="Word (*.doc);;*.doc;;Word (*.docx);;*.docx;;All File (*.*);;*.*"excel_filter="Excel (*.xls);;*.xls;;Excel (*.xlsx);;*.xlsx;;All File (*.*);;*.*"pdf_filter="PDF (*.pdf);;*.pdf;;All File (*.*);;*.*"image_filter="Image Files (*.BMP;*.bmp;*.JPG;*.jpg;*.GIF;*.gif;*.png;*.PNG);;*.BMP;*.bmp;*.JPG;*.jpg;*.GIF;*.gif;*.png;*.PNG;;All File (*.*);;*.*"html_filter="HTML files (*.html;*.htm);;*.html;*.htm;;All files (*.*);;*.*"access_filter="Access (*.mdb);;*.mdb;;All File (*.*);;*.*"zip_filter="Zip (*.zip);;*.zip;;Rar (*.rar);;*.rar;;All files (*.*);;*.*"config_filter="Configuration Files (*.cfg);;*.cfg;;All File (*.*);;*.*"txt_filter="Text (*.txt);;*.txt;;All files (*.*);;*.*"xml_filter="XML Files (*.xml);;*.xml;;All files (*.*);;*.*"rar_filter="Rar (*.rar);;*.rar;;All files (*.*);;*.*"sqlite_filter="Sqlite Files (*.db);;*.db;;All files (*.*);;*.*"python_filter="Python Files (*.py);;*.py;;All files (*.*);;*.*"csv_filter="CSV Files (*.csv);;*.csv;;All files (*.*);;*.*"@staticmethoddefopen_file( parent: QWidget=None, multiple: bool=False, title: str="打开文件", filter: str=all_filter, filename: str="", initial_directory: str=os.getcwd(), )->str:"""打开文件对话框 :param parent: 父窗口 :param multiple: 是否多选 :param title: 对话框标题 :param filename: 默认文件名 :param filter: 文件过滤器 :param initial_directory: 默认目录 :return: 选中的文件路径,如果是多选,则返回以逗号分隔的多个文件路径"""#创建文件对话框dialog =QFileDialog(parent) dialog.setWindowTitle(title) dialog.setFileMode( QFileDialog.FileMode.ExistingFilesifmultipleelseQFileDialog.FileMode.ExistingFile ) dialog.setNameFilter(filter) dialog.setDirectory(initial_directory) dialog.selectFile(filename)#执行对话框并获取文件路径result =""ifdialog.exec():ifmultiple: file_paths=dialog.selectedFiles() result=",".join(file_paths)#将文件路径连接成一个字符串else: result= dialog.selectedFiles()[0]#获取单个文件路径returnresult

当然上面open_file传入的是所有文件的格式,如果我们需要跟进一步选择Excel格式,就需要传入对应的后缀名参数常量即可。如下所示。

而如果要弹出保存文件对话框的操作,那么我们也是如法炮制即可。

@staticmethoddefsave_file( parent: QWidget=None, title: str="保存文件", filter: str=all_filter, filename: str="", initial_directory: str=os.getcwd(), )->str:"""以指定的标题弹出保存文件对话框 :param title: 对话框标题 :param filename: 默认文件名 :param filter: 文件过滤器 :param initial_directory: 默认目录 :return: 选中的文件路径"""#创建保存文件对话框dialog =QFileDialog(parent) dialog.setWindowTitle(title) dialog.setAcceptMode(QFileDialog.AcceptMode.AcceptSave)#设置为保存模式dialog.setNameFilter(filter) dialog.setDirectory(initial_directory) dialog.selectFile(filename)#执行对话框并获取文件路径result =""ifdialog.exec(): result= dialog.selectedFiles()[0]#获取选中的文件路径returnresult

其他类型格式的,只需要传入对应的filter格式即可。

选择目录也是类似的处理

@staticmethoddefopen_dir( parent: QWidget=None, title: str="选择目录", initial_directory: str=os.getcwd(), )->str:"""显示目录选择对话框"""#创建文件对话框dialog =QFileDialog(parent) dialog.setWindowTitle(title) dialog.setFileMode(QFileDialog.FileMode.Directory)#设置为目录选择模式dialog.setOption(QFileDialog.Option.ShowDirsOnly, True)#只显示目录dialog.setDirectory(initial_directory)#执行对话框并获取选中的目录result =""ifdialog.exec(): result= dialog.selectedFiles()[0]#获取选中的目录路径print(result)returnresult

选择多个目录,如下效果

这样我们在一些窗体上使用保存Excel或者PDF文件的时候,直接使用它的函数调用即可,比较简单了。

defexport_to_pdf(self, setting: PrintSetting) ->str:"""将 QTableView 的数据导出为 PDF, 成功返回文件路径,失败返回空字符串"""pdf_file=FileDialogUtil.save_pdf(filename=f"{setting.print_title}.pdf")ifnotpdf_file:return""#创建 QPrinter,PDF格式printer =QPrinter(QPrinter.PrinterMode.HighResolution) printer.setOutputFormat(QPrinter.OutputFormat.PdfFormat) printer.setOutputFileName(pdf_file)#输出 PDF 文件#打印的处理printer.setPageSize(setting.page_size) printer.setPageOrientation(setting.page_orientation) self.print_cols= setting.print_cols#打印指定列的索引列表self.print_title = setting.print_title#打印标题self.settings = setting#保存打印设置#打印输出self.print_preview_paint(printer)returnpdf_file

3、封装常用消息对话框

封装的消息提示对话框包括个各种常用的对话框,如下所示:

首先我们需要定义一个独立的消息对话框类MessageUtil,如下所示。

classMessageUtil:"""封装了常用的消息对话框,以方便使用常用对话框消息。 包括提示信息、警告信息、错误信息、确认信息、询问信息、输入信息、 选择信息、多选信息、文件选择信息、目录选择信息、字体选择信息、颜色选择信息、进度条信息等。"""#常用消息对话框的标题CAPTION_TIPS ="提示信息"CAPTION_WARNING="警告信息"CAPTION_ERROR="错误信息"CAPTION_CONFIRM="确认信息"@staticmethoddefshow_message( message: str, title: str=CAPTION_TIPS, extended_message=None, parent=None, icon: QMessageBox.Icon=QMessageBox.Icon.Information, buttons: QMessageBox.StandardButton=QMessageBox.StandardButton.Ok, )->QMessageBox.StandardButton:"""通用消息框显示函数"""msg_box=QMessageBox(parent) msg_box.setWindowTitle(title) msg_box.setText(message)#设置详细信息,在消息框的底部显示。ifextended_message:#创建 TextSplitter 实例,设置每行最大字符数为 30splitter = TextSplitter(max_line_length=80)#使用 splitter 来分割文本extended_message =splitter.split(extended_message) msg_box.setDetailedText(extended_message) msg_box.setDetailedText(extended_message) msg_box.setIcon(icon) msg_box.setStandardButtons(buttons)#设置窗口图标app_icon = QIcon("app/images/app.ico") msg_box.setWindowIcon(app_icon)returnmsg_box.exec()

然后统一对常用的消息进行函数封装,如一般消息、警告消息、错误消息,提示消息等,只需要对上面函数的简单调用,传递不同的参数就可以。

有了这样的封装,我们可以在窗体中直接调用,不需要记住太多的参数了,比较简单,如下面的删除操作处理。

@asyncSlot() asyncdefOnDelete(self):"""弹出删除对话框"""selected_rows=self.table_view.selectionModel().selectedRows()ifnotselected_rows:MessageUtil.show_info("请选择要操作的行")return#确认删除result =MessageUtil.show_confirm("确认删除选中的行?","确认删除")ifresult:#遍历选定的行,删除主键值对应的记录list =[]forindexinselected_rows: entity_id=self.table_model.GetPrimaryKeyValue(index.row())ifentity_id: list.append(entity_id)try: await self.OnDeleteByIdList(list)exceptException as e:MessageUtil.show_error(f"删除失败:{e}")

为了了解常用对话框的操作,我们还编写一个简单的测试界面来展示效果。

字体对话框

封装字体对话框函数如下:

@staticmethoddefshow_font_dialog(parent=None, font=None) ->tuple[QFont, bool]:"""显示字体选择对话框 :param parent: 父窗口 :param font: 默认字体,如果没有提供,使用系统默认字体 :return: 选择的字体,成功时返回 (QFont, True),失败时返回 (None, False)"""#如果没有提供默认字体,则使用系统默认字体iffontisNone: font= QApplication.font()#获取系统默认字体#打开字体选择对话框ok, selected_font =QFontDialog.getFont(font, parent)#返回选择的字体和是否成功returnselected_font, ok

调用代码如下所示。

defon_select_font(self): myfont= self.message.font()#获取当前字体font_data= MessageUtil.show_font_dialog(self, myfont)[0]#打开字体选择对话框iffont_data: self.message.setFont( QFont(font_data.family(), font_data.pointSize()) )#设置字体self.message.update()#刷新显示

颜色对话框

封装颜色对话框函数如下:

defshow_colour_dialog(parent=None, colour=None) ->tuple[QColor, bool]:"""显示颜色选择对话框 :param parent: 父窗口 :param colour: 默认颜色,如果没有提供,使用黑色 :return: 选择的颜色,成功时返回 (QColor, True),失败时返回 (None, False)"""#如果没有提供默认颜色,则使用黑色ifcolourisNone: colour=QColor(Qt.GlobalColor.black)#打开颜色选择对话框selected_colour =QColorDialog.getColor(colour, parent)#返回选择的颜色和是否成功returnselected_colour, selected_colour.isValid()

调用代码如下所示。

defon_select_colour(self):color=self.message.palette().color(QPalette.ColorRole.WindowText) color_data=MessageUtil.show_colour_dialog(self, color)[0]ifcolor_data: self.message.setStyleSheet(f"color: {color_data.name()};") self.message.update()#刷新显示

通过上面的简单封装,我们就可以很容易的记得相关的处理函数,并且尽可能的减少了相关的参数传递,这样我们在使用的时候,更加方便灵活了。

专注于代码生成工具、.Net/Python 框架架构及软件开发,以及各种Vue.js的前端技术应用。著有Winform开发框架/混合式开发框架、微信开发框架、Bootstrap开发框架、ABP开发框架、SqlSugar开发框架、Python开发框架等框架产品。
转载请注明出处:撰写人:伍华聪 http://www.iqidi.com
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/15 18:12:36

JS事件循环

单线程的 JavaScript同步与异步js本身是单线程的,为了处理异步任务,宿主环境(浏览器/v8)会将其交给其他线程处理,执行js的线程则会立即结束当前任务而去执行后续代码事件循环事件循环是宿主环境处理js异步操作的方式,让其能够非阻…

作者头像 李华
网站建设 2026/5/16 13:15:24

【稀缺技术曝光】:Open-AutoGLM邮件语义理解与多标签分类突破方案

第一章:Open-AutoGLM邮件语义理解与多标签分类突破方案背景与挑战 企业级邮件系统每天处理海量非结构化文本,传统规则匹配方法在语义泛化和标签扩展方面存在明显瓶颈。Open-AutoGLM 通过融合生成式预训练与自监督多标签学习机制,实现了对复杂…

作者头像 李华
网站建设 2026/5/16 13:16:01

为什么顶尖科技公司都在用Open-AutoGLM做邮件自动回复?真相曝光

第一章:为什么顶尖科技公司都在用Open-AutoGLM做邮件自动回复?在当今快节奏的商业环境中,高效处理海量邮件成为科技公司提升运营效率的关键。Open-AutoGLM 作为一款基于开源大语言模型的自动化邮件应答系统,正被 Google、Meta 和 …

作者头像 李华
网站建设 2026/5/16 13:15:40

Open-AutoGLM实战指南:5步搭建高精度邮件分类模型(零基础可学)

第一章:Open-AutoGLM邮件分类模型概述Open-AutoGLM 是一款基于开源大语言模型架构的智能邮件分类系统,专为高效识别和归类电子邮件内容而设计。该模型融合了自然语言理解与自动化标签生成能力,能够在无需人工干预的前提下,准确区分…

作者头像 李华
网站建设 2026/5/16 14:19:51

Open-AutoGLM邮件处理全解析,深度掌握AI驱动的智能过滤核心技术

第一章:Open-AutoGLM邮件分类筛选在现代企业通信中,邮件系统承载着大量关键信息,如何高效地对海量邮件进行自动化分类与筛选成为提升工作效率的重要课题。Open-AutoGLM 是一个基于开源大语言模型的智能邮件处理框架,能够结合自然语…

作者头像 李华
网站建设 2026/5/16 14:20:19

通达信趋势中短长

{}A:MA(-100*(HHV(HIGH,34)-CLOSE)/(HHV(HIGH,34)-LLV(LOW,34)),19); B:-100*(HHV(HIGH,14)-CLOSE)/(HHV(HIGH,14)-LLV(LOW,14)); D:EMA(-100*(HHV(HIGH,34)-CLOSE)/(HHV(HIGH,34)-LLV(LOW,34)),4); {} 长期线:A100,COLOR9900FF; 短期线:B100,COLOR888888; 中期线:D100,COLORYE…

作者头像 李华