找回密码
 立即注册
首页 业界区 业界 使用PySide6/PyQt6实现系统图标的展示和选择处理 ...

使用PySide6/PyQt6实现系统图标的展示和选择处理

焦听云 昨天 20:48
在我们的基于PySide6/PyQt6的前端应用中,为了方便和重用,我们收集一些系统图标作为界面的使用,另外PySide/PyQt内部也有内置的图标,我们可以结合起来对图标进行统一的展示和选择处理,如在系统定义动态菜单的时候,我们可以为它指定具体的图标,从而灵活定义菜单的相关展示效果。
1、使用PySide6/PyQt6实现系统图标的展示和选择处理

1.png

 如上面所示,我们在菜单管理中需要汇总系统的相关图标,以便在菜单编辑中选择具体的图标效果。
2.png

选择图标会弹出一个可缩放的对话框出来,如下界面所示。
3.png

上面的图标对话框,我们为了更好的展现效果,使用一个自己封装好的可伸缩调整大小的对话框基类,如下关系
  1. class MySizedDialog(QDialog):
  2.     """自定义对话框基类"""
  3.     def __init__(
  4.         self,
  5.         parent,
  6.         title="默认对话框标题",
  7.         can_scroll=True,
  8.         show_btn_ok=True,
  9.         size=(400, 600),
  10.         pos=None,
  11.     ):
  12.         super().__init__(parent)
  13.         self.log = settings.log.get_logger()
  14.         self.setWindowTitle(title)
  15.         self.setWindowIcon(images.catalog["appIcon"])
  16.         self.show_btn_ok = show_btn_ok
  17.         self.can_scroll = can_scroll
复制代码
关于可伸缩的对话框基类,我们在控件界面的底部,根据配置创建OK、Cancel的标准按钮集合,如下代码所示。
  1.     def _add_buttons(self) -> QDialogButtonBox:
  2.         """创建按钮"""
  3.         if self.show_btn_ok:  # OK按钮、Cancel按钮都显示
  4.             # 创建标准按钮框(包括 OK 和 Cancel)
  5.             button_box = QDialogButtonBox(
  6.                 QDialogButtonBox.StandardButton.Ok
  7.                 | QDialogButtonBox.StandardButton.Cancel
  8.             )
  9.         else:  # 只显示 Cancel 按钮
  10.             button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Cancel)
  11.         # 查找 OK 按钮
  12.         ok_button = button_box.button(QDialogButtonBox.StandardButton.Ok)
  13.         if ok_button:  # 检查按钮是否存在
  14.             # 设置图标
  15.             ok_button.setIcon(images.catalog["accept"])
  16.             # 异步绑定事件
  17.             ok_button.clicked.connect(self.on_ok)
  18.         cancel_button = button_box.button(QDialogButtonBox.StandardButton.Cancel)
  19.         if cancel_button:  # 检查按钮是否存在
  20.             # 设置图标
  21.             cancel_button.setIcon(images.catalog["cancel"])
  22.             # 异步绑定事件
  23.             cancel_button.clicked.connect(self.on_cancel)
  24.         return button_box
复制代码
 
然后再构建一个图标选择的控件类即可,如下所示。
  1. class MyImageDialog(ctrl.MySizedDialog):
  2.     """图片选择对话框"""
  3.     selected_name = ""
  4.     selected_bitmap = None
  5.     def __init__(
  6.         self,
  7.         parent,
  8.         title="图片选择对话框",
  9.         can_scroll=True,
  10.         show_btn_ok=True,
  11.         size=(800, 600),
  12.         pos=None,
  13.         return_icon_size=32,
  14.     ):
  15.         super().__init__(
  16.             parent,
  17.             title=title,
  18.             can_scroll=can_scroll,
  19.             show_btn_ok=show_btn_ok,
  20.             size=size,
  21.             pos=pos,
  22.         )
  23.         self.return_icon_size = return_icon_size
复制代码
 
4.png

 我们在图标选择的对话框,使用了选项卡控件来构建两个界面,一个是展示我们自定义的图标集合,一个是展示系统的内置图标集合。
  1.     def add_contents(self, panel: QWidget, grid_sizer: QGridLayout):
  2.         """创建列表面板"""
  3.         # 创建 QTabWidget
  4.         self.notebook =<strong> QTabWidget</strong>(<strong>panel</strong>)
  5.         self.notebook.setTabPosition(QTabWidget.TabPosition.North)
  6.         self.first = self.<strong>create_first</strong>()
  7.         self.second = self.<strong>create_second</strong>()
  8.         self.notebook.addTab(self.first, get_bitmap("group"), "自定义内嵌图片")
  9.         self.notebook.addTab(self.second, get_bitmap("group_key"), "系统图标")
  10.         # 创建 QLabel,用于显示图片
  11.         self.bmpCtrl = QLabel(panel)
  12.         # self.bmpCtrl.setFixedSize(32, 32)  # 设置固定大小
  13.         self.bmpCtrl.setStyleSheet("border: 1px solid black;")  # 设置边框样式
  14.         self.bmpCtrl.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)  # 设置尺寸策略
  15.         grid_sizer.addWidget(self.notebook)
  16.         grid_sizer.addWidget(self.bmpCtrl)<br>
复制代码
 我们以自定义的图表集合为例,我们创建的第一个create_first()函数 里面就是根据集合遍历进行展示,如下代码。
  1.     def create_first(self) -> QWidget:
  2.         """创建自定义内嵌图片面板"""
  3.         # 创建面板
  4.         panel = self._create_window(self, True)
  5.         # 创建 WrapSizer
  6.         icon_layout = ctrl.FlowLayout()
  7.         # 遍历图片目录,创建图标
  8.         for idx, (key, value) in<strong> enumerate(images.catalog.items())</strong>:
  9.             icon_panel = self.create_icon(panel, value, key)
  10.             icon_layout.addWidget(icon_panel)
  11.         child_panel = QWidget(panel)
  12.         child_panel.setLayout(icon_layout)
  13.         if isinstance(panel, QScrollArea):
  14.            panel.setWidget(child_panel)
  15.         return panel
复制代码
 
而其中images是我们导入的系统全局图标集合,它是在系统初始化的时候进行内存加载,驻留全局使用的。
  1. from core.core_images import CoreImages as images
复制代码
 
 我们是在登录界面初始化的时候,就对系统全局图标集合进行加载的。
5.png

 我们和WxPython 的做法类似,使用Base64编码进行图片处理,其中Base64编码我们通过辅助类来构建生成。
6.png

 如果需要根据文件生成base64编码,单独运行辅助类即可,它运行提示输入文件,或者拖入文件即可获得文件名,运行后生成Base64编码和相关代码,拷贝过去使用即可。
7.png

8.png

 对于PySide/PyQT的内置图标
9.png

 我们可以通过遍历 QStyle.StandardPixmap 来获取并展示的
  1.         # 创建 WrapSizer
  2.         icon_layout = ctrl.FlowLayout()
  3.         # 获取所有标准图标
  4.         i = 0
  5.         for standard_icon in QStyle.StandardPixmap:
  6.             icon = QApplication.style().standardIcon(standard_icon)  # 获取标准图标
  7.             # 检查图标是否有效
  8.             if icon.isNull():
  9.                 # print(f"跳过无效图标: {standard_icon.name}")
  10.                 continue
  11.             pixmap_32 = icon.pixmap(32, 32)  # 生成 32x32 的 QPixmap
  12.             icon_32 = QIcon(pixmap_32)  # 重新创建 QIcon
  13.             name = standard_icon.name  # 获取图标名称
  14.             icon_panel = self.create_icon(panel, icon_32, name)
  15.             icon_layout.addWidget(icon_panel)
  16.             i += 1
复制代码
 
在图标展示后,每个图标都在接收单击事件后,传入对象的相关信息,因此选中并确认后返回图标的信息。
  1.    def on_item_selected(self, event, name: str):
  2.         """鼠标左键单击事件处理"""
  3.         icon = get_bitmap(name, self.return_icon_size)
  4.         bitmap = icon.pixmap(32, 32)
  5.         bitmap = bitmap.scaled(32, 32, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation)
  6.         self.selected_name = name
  7.         self.selected_bitmap = bitmap
  8.         self.bmpCtrl.setPixmap(bitmap)
  9.         print(f"你选择了: {name}")
复制代码
 
这样我们就可以根据名称进行图标的展示了。
我们在bitmap_util.py的辅助类中定义获取图标为位图对象QIcon的转换,如下是根据名称生成对应的位图对象QIcon。
  1. def get_bitmap(name: str, icon_size: int = 32) -> QIcon:
  2.     """获取位图,可以根据名称获取images里面的内容,或者是系统内置的图标SP_XXX"""
  3.     if name is None or name == "":
  4.         name = "appIcon"
  5.     if name.startswith("SP_"):
  6.         # 系统内置的图标
  7.         icon = get_standard_icon(name, icon_size)
  8.         return icon
  9.     elif name.startswith("ic_fluent_"):
  10.         # 微软Fluent系统图标
  11.         icon = FluentSystemIconUtil.create_icon_by_name(name, icon_size)
  12.         return icon
  13.     else:
  14.         # 自定义内置的图标
  15.         icon = get_customed_icon_with_default(name, icon_size)
  16.         return icon
复制代码
 
以上就是基于PySide6/PyQt6的前端应用中,对自定义的图标资源以及内置图标资源进行整合的展示处理,以及如何生成base64编码,加载显示图标的一整个过程。
 

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册