使用PySide6/PyQt6實現系統圖標的展示和選擇處理
在我們的基于PySide6/PyQt6的前端應用中,為了方便和重用,我們收集一些系統圖標作為界面的使用,另外PySide/PyQt內部也有內置的圖標,我們可以結合起來對圖標進行統一的展示和選擇處理,如在系統定義動態菜單的時候,我們可以為它指定具體的圖標,從而靈活定義菜單的相關展示效果。
1、使用PySide6/PyQt6實現系統圖標的展示和選擇處理

如上面所示,我們在菜單管理中需要匯總系統的相關圖標,以便在菜單編輯中選擇具體的圖標效果。

選擇圖標會彈出一個可縮放的對話框出來,如下界面所示。

上面的圖標對話框,我們為了更好的展現效果,使用一個自己封裝好的可伸縮調整大小的對話框基類,如下關系
class MySizedDialog(QDialog): """自定義對話框基類""" def __init__( self, parent, title="默認對話框標題", can_scroll=True, show_btn_ok=True, size=(400, 600), pos=None, ): super().__init__(parent) self.log = settings.log.get_logger() self.setWindowTitle(title) self.setWindowIcon(images.catalog["appIcon"]) self.show_btn_ok = show_btn_ok self.can_scroll = can_scroll
關于可伸縮的對話框基類,我們在控件界面的底部,根據配置創建OK、Cancel的標準按鈕集合,如下代碼所示。
def _add_buttons(self) -> QDialogButtonBox: """創建按鈕""" if self.show_btn_ok: # OK按鈕、Cancel按鈕都顯示 # 創建標準按鈕框(包括 OK 和 Cancel) button_box = QDialogButtonBox( QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel ) else: # 只顯示 Cancel 按鈕 button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Cancel) # 查找 OK 按鈕 ok_button = button_box.button(QDialogButtonBox.StandardButton.Ok) if ok_button: # 檢查按鈕是否存在 # 設置圖標 ok_button.setIcon(images.catalog["accept"]) # 異步綁定事件 ok_button.clicked.connect(self.on_ok) cancel_button = button_box.button(QDialogButtonBox.StandardButton.Cancel) if cancel_button: # 檢查按鈕是否存在 # 設置圖標 cancel_button.setIcon(images.catalog["cancel"]) # 異步綁定事件 cancel_button.clicked.connect(self.on_cancel) return button_box
然后再構建一個圖標選擇的控件類即可,如下所示。
class MyImageDialog(ctrl.MySizedDialog): """圖片選擇對話框""" selected_name = "" selected_bitmap = None def __init__( self, parent, title="圖片選擇對話框", can_scroll=True, show_btn_ok=True, size=(800, 600), pos=None, return_icon_size=32, ): super().__init__( parent, title=title, can_scroll=can_scroll, show_btn_ok=show_btn_ok, size=size, pos=pos, ) self.return_icon_size = return_icon_size

我們在圖標選擇的對話框,使用了選項卡控件來構建兩個界面,一個是展示我們自定義的圖標集合,一個是展示系統的內置圖標集合。
def add_contents(self, panel: QWidget, grid_sizer: QGridLayout): """創建列表面板""" # 創建 QTabWidget self.notebook = QTabWidget(panel) self.notebook.setTabPosition(QTabWidget.TabPosition.North) self.first = self.create_first() self.second = self.create_second() self.notebook.addTab(self.first, get_bitmap("group"), "自定義內嵌圖片") self.notebook.addTab(self.second, get_bitmap("group_key"), "系統圖標") # 創建 QLabel,用于顯示圖片 self.bmpCtrl = QLabel(panel) # self.bmpCtrl.setFixedSize(32, 32) # 設置固定大小 self.bmpCtrl.setStyleSheet("border: 1px solid black;") # 設置邊框樣式 self.bmpCtrl.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) # 設置尺寸策略 grid_sizer.addWidget(self.notebook) grid_sizer.addWidget(self.bmpCtrl)
我們以自定義的圖表集合為例,我們創建的第一個create_first()函數 里面就是根據集合遍歷進行展示,如下代碼。
def create_first(self) -> QWidget: """創建自定義內嵌圖片面板""" # 創建面板 panel = self._create_window(self, True) # 創建 WrapSizer icon_layout = ctrl.FlowLayout() # 遍歷圖片目錄,創建圖標 for idx, (key, value) in enumerate(images.catalog.items()): icon_panel = self.create_icon(panel, value, key) icon_layout.addWidget(icon_panel) child_panel = QWidget(panel) child_panel.setLayout(icon_layout) if isinstance(panel, QScrollArea): panel.setWidget(child_panel) return panel
而其中images是我們導入的系統全局圖標集合,它是在系統初始化的時候進行內存加載,駐留全局使用的。
from core.core_images import CoreImages as images
我們是在登錄界面初始化的時候,就對系統全局圖標集合進行加載的。

我們和WxPython 的做法類似,使用Base64編碼進行圖片處理,其中Base64編碼我們通過輔助類來構建生成。

如果需要根據文件生成base64編碼,單獨運行輔助類即可,它運行提示輸入文件,或者拖入文件即可獲得文件名,運行后生成Base64編碼和相關代碼,拷貝過去使用即可。


對于PySide/PyQT的內置圖標

我們可以通過遍歷 QStyle.StandardPixmap 來獲取并展示的
# 創建 WrapSizer icon_layout = ctrl.FlowLayout() # 獲取所有標準圖標 i = 0 for standard_icon in QStyle.StandardPixmap: icon = QApplication.style().standardIcon(standard_icon) # 獲取標準圖標 # 檢查圖標是否有效 if icon.isNull(): # print(f"跳過無效圖標: {standard_icon.name}") continue pixmap_32 = icon.pixmap(32, 32) # 生成 32x32 的 QPixmap icon_32 = QIcon(pixmap_32) # 重新創建 QIcon name = standard_icon.name # 獲取圖標名稱 icon_panel = self.create_icon(panel, icon_32, name) icon_layout.addWidget(icon_panel) i += 1
在圖標展示后,每個圖標都在接收單擊事件后,傳入對象的相關信息,因此選中并確認后返回圖標的信息。
def on_item_selected(self, event, name: str): """鼠標左鍵單擊事件處理""" icon = get_bitmap(name, self.return_icon_size) bitmap = icon.pixmap(32, 32) bitmap = bitmap.scaled(32, 32, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation) self.selected_name = name self.selected_bitmap = bitmap self.bmpCtrl.setPixmap(bitmap) print(f"你選擇了: {name}")
這樣我們就可以根據名稱進行圖標的展示了。
我們在bitmap_util.py的輔助類中定義獲取圖標為位圖對象QIcon的轉換,如下是根據名稱生成對應的位圖對象QIcon。
def get_bitmap(name: str, icon_size: int = 32) -> QIcon: """獲取位圖,可以根據名稱獲取images里面的內容,或者是系統內置的圖標SP_XXX""" if name is None or name == "": name = "appIcon" if name.startswith("SP_"): # 系統內置的圖標 icon = get_standard_icon(name, icon_size) return icon elif name.startswith("ic_fluent_"): # 微軟Fluent系統圖標 icon = FluentSystemIconUtil.create_icon_by_name(name, icon_size) return icon else: # 自定義內置的圖標 icon = get_customed_icon_with_default(name, icon_size) return icon
以上就是基于PySide6/PyQt6的前端應用中,對自定義的圖標資源以及內置圖標資源進行整合的展示處理,以及如何生成base64編碼,加載顯示圖標的一整個過程。
專注于代碼生成工具、.Net/Python 框架架構及軟件開發,以及各種Vue.js的前端技術應用。著有Winform開發框架/混合式開發框架、微信開發框架、Bootstrap開發框架、ABP開發框架、SqlSugar開發框架、Python開發框架等框架產品。
??轉載請注明出處:撰寫人:伍華聰??http://www.iqidi.com?
????
浙公網安備 33010602011771號