这几天在搞PyQt6的插件化开发,做到插件管理器的地方时出现的问题,点不同插件菜单现实的插件信息都是最后一个插件的
from libs.windows.Calculator import *
from PyQt6.QtGui import *
import importlib
import glob
plugins = {}
for i in glob.glob("plugins/*.py"):
plugin_file_name = i.replace("\\", ".").replace(".py", "")
if "__init__" not in plugin_file_name:
plugin = importlib.import_module(plugin_file_name)
plugins[plugin_file_name.replace("plugins.", "")] = plugin
functions = {} # FIXME: 问题出在这,我以为用字典存储函数,函数使用的全局变量被更改后函数是不会变的,但是我错了,这就导致信息函数指向的插件信息全是最后一个插件的
for i in plugins:
def info():
author = getattr(plugins[i], "__author__", "Unknown")
version = getattr(plugins[i], "__version__", "1.0.0")
if plugins[i].__doc__ is None:
doc = "\nNo document\n"
doc = plugins[i].__doc__
QMessageBox.information(calculator, "插件信息", f"插件文件名:{i}\n插件名称:{plugins[i].__name__}\n插件作者:{author}\n插件版本:{version}\n{doc}")
functions[i] = info
menus = {}
for i in plugins:
plugin_menu = QMenu(plugins[i].__name__, calculator.ui.plugins_menu)
plugin_menu.setObjectName(i)
calculator.ui.plugins_menu.addMenu(plugin_menu)
menus[i] = plugin_menu
actions = {}
for i in plugins:
plugin_menu_action = QAction("插件信息", menus[i])
plugin_menu_action.setObjectName(menus[i].objectName() + "_action")
plugin_menu_action.triggered.connect(functions[i])
actions[i] = plugin_menu_action
for i in plugins:
menus[i].addAction(actions[i])
所有插件菜单点击后显示的插件信息全都是最后一个的
我之前的思路是使用字典或列表存储函数,但是我发现函数使用的全局变量被更改后,函数即使被存储在字典中也是会改变的,所以我遍历完插件信息字典后,所有函数指向的插件信息就全是最后一个插件的了
点击不同的插件菜单,显示对应插件的信息
解决了,写一个闭包就好了
附上代码(虽然写得很难看,但好歹能跑了)
from libs.windows.Calculator import *
from PyQt6.QtGui import *
import importlib
import glob
plugins = {}
for i in glob.glob("plugins/*.py"):
plugin_file_name = i.replace("\\", ".").replace(".py", "")
if "__init__" not in plugin_file_name:
plugin = importlib.import_module(plugin_file_name)
plugins[plugin_file_name.replace("plugins.", "")] = plugin
def info():
def _info(i):
if plugins[i].__doc__ is None:
doc = "\nNo document\n"
doc = plugins[i].__doc__
return {
"name": plugins[i].__name__,
"author": getattr(plugins[i], "__author__", "Unknown"),
"version": getattr(plugins[i], "__version__", "1.0.0"),
"document": doc,
"show": lambda: QMessageBox.information(calculator, "插件信息", f"插件文件名:{i}\n插件名称:{plugins[i].__name__}\n插件作者:{getattr(plugins[i], '__author__', 'Unknown')}\n插件版本:{getattr(plugins[i], '__version__', '1.0.0')}\n{doc}")
}
functions = {}
for i in plugins:
functions[i] = _info(i)
return functions
menus = {}
for i in info():
plugin_menu = QMenu(info()[i]["name"], calculator.ui.plugins_menu)
plugin_menu.setObjectName(i)
calculator.ui.plugins_menu.addMenu(plugin_menu)
menus[i] = plugin_menu
actions = {}
for i in info():
plugin_menu_action = QAction("插件信息", menus[i])
plugin_menu_action.setObjectName(menus[i].objectName() + "_action")
plugin_menu_action.triggered.connect(info()[i]["show"])
actions[i] = plugin_menu_action
for i in info():
menus[i].addAction(actions[i])
plugins是个字典
遍历的时候应该
for k,v in plugins.items():
你这for i in plugins是个什么语法
而且还能plugins[i]这样用?你plugins到底是个什么,是不是一会是dict一会是list
-=-==-
还有,你这是个典型的闭包问题
info应该有参数,i应该作为参数传进来
否则info最后肯定是只有一个值,而不是对应每个i都有一个对应的info