基本完成
This commit is contained in:
parent
904b59d71c
commit
4b6072f8fb
16 changed files with 276 additions and 820 deletions
|
@ -1,350 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os, time, sys , importlib, sip
|
||||
|
||||
#__file__ 为此文件路径 , 在ipython里是测不出来的
|
||||
pluginsManagerPath = os.path.dirname(os.path.abspath(__file__))
|
||||
#主脚本目录
|
||||
mainPath = os.path.dirname(pluginsManagerPath)
|
||||
#自定义插件目录
|
||||
pluginsPath = os.path.join( mainPath, "Plugins")
|
||||
#以后可能会有其他插件目录
|
||||
AllPluginsPath = {"customer":pluginsPath}
|
||||
#设置模块搜索路径
|
||||
for key in AllPluginsPath :
|
||||
if AllPluginsPath[key] not in sys.path:
|
||||
sys.path.insert(0, AllPluginsPath[key])
|
||||
|
||||
from copy import deepcopy
|
||||
|
||||
from PyQt5.QtCore import *
|
||||
from PyQt5.QtGui import *
|
||||
from PyQt5.QtWidgets import *
|
||||
|
||||
from PluginManager.PluginStore import PluginStore
|
||||
from PluginManager.PluginStore.StoreModel import FileModel
|
||||
|
||||
from Tools.pmf_myjson import *
|
||||
|
||||
"setting_flie -> From Tools.pmf_myjson , json写入的位置"
|
||||
|
||||
class PluginManager(QObject):
|
||||
"""
|
||||
管理插件的加载 , 卸载 , 文件的添加/删除监控.
|
||||
"""
|
||||
def __init__(self, parent=None, *args, **kwargs):
|
||||
super(PluginManager, self).__init__(parent, *args, **kwargs)
|
||||
self.__mw = parent
|
||||
self.__initUI()
|
||||
|
||||
self.pluginDirs = {"pluginFolder": os.path.join(
|
||||
os.path.abspath("./"),
|
||||
"Plugins"), }
|
||||
|
||||
self.header = ["PlugName",
|
||||
"Allow", "CreateTime", "ModifyTime"]
|
||||
|
||||
self.pluginsInfo = {
|
||||
"StartModule": {},
|
||||
|
||||
}
|
||||
# self.jsonPlugin :{插件名:{header参数}}
|
||||
|
||||
self.jsonPlugin = None
|
||||
|
||||
def __initUI(self):
|
||||
"""
|
||||
|
||||
"""
|
||||
mw = self.__mw
|
||||
if mw.findChild(QMenuBar, "menuBar"):
|
||||
# 插入到mainwindow的menuBar下 , 点击查看弹出插件加载情况窗体===
|
||||
mw.menuPlugin = QAction("Plugin", self.__mw.menuBar,
|
||||
triggered=self.__createPluginStoreDialog)
|
||||
|
||||
mw.menuBar.addAction(self.__mw.menuPlugin)
|
||||
# 插入到mainwindow的menuBar下 , 点击查看弹出插件加载情况窗体===
|
||||
else:
|
||||
QMessageBox.information(mw, "", "主窗体没有菜单栏, 请先创建.")
|
||||
|
||||
# 文件监听器
|
||||
|
||||
self.model = FileModel(self)
|
||||
self.model.setRootPath("./Plugins")
|
||||
self.model.setFilter(QDir.Files)
|
||||
self.model.setNameFilters(["Plugin*.py"])
|
||||
self.model.setNameFilterDisables(False);
|
||||
self.index = self.model.index("./Plugins")
|
||||
|
||||
self.model.directoryLoaded.connect(self.start)
|
||||
|
||||
def __createPluginStoreDialog(self):
|
||||
"""
|
||||
显示插件加载情况的 窗体.
|
||||
"""
|
||||
if not hasattr(self, "dia"):
|
||||
self.dia = PluginStore.PluginStore(self, self.__mw)
|
||||
|
||||
self.dia.show()
|
||||
|
||||
|
||||
def m_rowsRemoved(self, index, first, last):
|
||||
"""
|
||||
文件被删除或重命名时候被调用.
|
||||
"""
|
||||
print("removeName:", self.model.index(first, 0, index).data(),first )
|
||||
mod = (self.model.index(first, 0, index).data())[:-3]
|
||||
|
||||
self.unload(mod)
|
||||
self.pluginsInfo["StartModule"].pop(mod)
|
||||
self.delJson(self.jsonPlugin , self.pluginsInfo["StartModule"])
|
||||
|
||||
# pop的步骤u已经在deljson中执行
|
||||
# self.jsonPlugin.pop(mod)
|
||||
|
||||
def m_rowsInserted(self, index, first, last):
|
||||
"""
|
||||
文件增加或重命名时候被调用.
|
||||
"""
|
||||
print("insertName:", self.model.index(first, 0, index).data(), first)
|
||||
f = self.model.index(first, 0, index).data()
|
||||
mod = f[:-3]
|
||||
|
||||
fullPath = os.path.join(self.pluginDirs["pluginFolder"], f)
|
||||
self.pluginsInfo["StartModule"][mod] = {"path": fullPath}
|
||||
mod, data = self.addJson(fullPath, mod)
|
||||
|
||||
self.jsonPlugin[mod] = data
|
||||
|
||||
self.load(mod)
|
||||
|
||||
def start(self):
|
||||
"""
|
||||
self.model 异步加载完成之后开始调用 self.startGetPlugin.
|
||||
"""
|
||||
self.jsonPlugin = self.startGetPlugin(self.pluginDirs['pluginFolder'])
|
||||
# print("jsonPlugin:", self.jsonPlugin,"\n",
|
||||
# "pluginsModule:", self.pluginsInfo)
|
||||
self.loadAll()
|
||||
|
||||
self.model.rowsAboutToBeRemoved.connect(self.m_rowsRemoved)
|
||||
self.model.rowsInserted.connect(self.m_rowsInserted)
|
||||
self.model.directoryLoaded.disconnect(self.start)
|
||||
self.__createPluginStoreDialog()
|
||||
|
||||
def startGetPlugin(self, pluginFolder: "./Plugins", CHANGE=False) -> "FoJson":
|
||||
"""
|
||||
1 . 程序启动加载插件.
|
||||
"""
|
||||
try:
|
||||
jsonPlugin = mfunc_readJson(setting_flie)
|
||||
|
||||
except:
|
||||
jsonPlugin = {}
|
||||
|
||||
pluginInfo = {}
|
||||
|
||||
rowCount = self.model.rowCount(self.index)
|
||||
|
||||
for row in range(rowCount):
|
||||
index = self.model.index(row, 0, self.index)
|
||||
# 文件名
|
||||
f = index.data()
|
||||
# 去掉后缀 , 加入模块
|
||||
module = f[:-3]
|
||||
fullPath = os.path.join(pluginFolder, f)
|
||||
|
||||
pluginInfo[module] = {"path": fullPath}
|
||||
try:
|
||||
if module not in jsonPlugin:
|
||||
self.addJson(fullPath, module)
|
||||
except:
|
||||
self.addJson(fullPath, module)
|
||||
|
||||
if CHANGE is False:
|
||||
self.pluginsInfo["StartModule"] = deepcopy(pluginInfo)
|
||||
|
||||
jsonPlugin = self.delJson(jsonPlugin, pluginInfo)
|
||||
|
||||
# print("jsonPlugin",jsonPlugin, "\n", "pluginInfo",pluginInfo )
|
||||
|
||||
return jsonPlugin
|
||||
|
||||
def addJson(self, fullPath, module) -> "ToJson":
|
||||
"""1.1写入插件 的json配置."""
|
||||
# 插件创建时间
|
||||
_ctime = time.localtime(os.stat(fullPath).st_ctime)
|
||||
ctime = time.strftime("%Y-%m-%d-%H:%M:%S", _ctime)
|
||||
# 插件修改时间
|
||||
_mtime = time.localtime(os.stat(fullPath).st_mtime)
|
||||
mtime = time.strftime("%Y-%m-%d-%H:%M:%S", _mtime)
|
||||
# 写入配置
|
||||
data = {
|
||||
self.header[1]: True, # allow
|
||||
self.header[2]: ctime, # cteateTime
|
||||
self.header[3]: mtime, # modifyTime
|
||||
}
|
||||
mfunc_AKrCVJson(module, data , self=self)
|
||||
|
||||
return module, data
|
||||
|
||||
def delJson(self, jsonPlugin, pluginInfo) -> "ToJson":
|
||||
"""
|
||||
1.2删除插件 的json配置.
|
||||
"""
|
||||
# 添加完重新加载一遍看是否有插件删除
|
||||
if jsonPlugin == {}:
|
||||
jsonPlugin = mfunc_readJson(setting_flie)
|
||||
|
||||
if len(jsonPlugin) - len(pluginInfo):
|
||||
long, short = jsonPlugin, pluginInfo
|
||||
else:
|
||||
long, short = pluginInfo, jsonPlugin
|
||||
|
||||
with open(setting_flie, 'a+', encoding='utf-8') as f:
|
||||
# 被删除的插件集合
|
||||
delPlugin = set(long) - set(short)
|
||||
for item in delPlugin:
|
||||
jsonPlugin.pop(item)
|
||||
# 写入配置
|
||||
mfunc_reDumpJson(f, jsonPlugin)
|
||||
|
||||
return jsonPlugin
|
||||
|
||||
# 加载所有插件
|
||||
def loadAll(self):
|
||||
"""
|
||||
2.加载所有模块.
|
||||
"""
|
||||
for mod in self.jsonPlugin:
|
||||
if self.jsonPlugin[mod]["Allow"]:
|
||||
try:
|
||||
self.load(mod)
|
||||
except:
|
||||
continue
|
||||
else:
|
||||
self.pluginsInfo["StartModule"][mod]["active"] = False
|
||||
|
||||
# 加载插件
|
||||
def load(self, mod: "str"):
|
||||
"""
|
||||
2.1 载入模块.
|
||||
"""
|
||||
try:
|
||||
# 动态载入模块
|
||||
_pluginModule = importlib.import_module(mod)
|
||||
|
||||
except:
|
||||
QMessageBox.information(self.__mw,
|
||||
"模块导入异常",
|
||||
"请在%s.py检查模块."%mod)
|
||||
|
||||
self.pluginsInfo["StartModule"][mod]["active"] = False
|
||||
|
||||
return False
|
||||
|
||||
self.instantiation(mod, _pluginModule)
|
||||
|
||||
return True
|
||||
|
||||
def instantiation(self , mod, moduleObj , NeedRplace = False):
|
||||
"""
|
||||
1.--实例化类.
|
||||
"""
|
||||
try:
|
||||
className = getattr(moduleObj, "className")
|
||||
pluginClass = getattr(moduleObj, className )
|
||||
except:
|
||||
self.pluginsInfo[mod]["active"] = False
|
||||
QMessageBox.information(self.__mw,
|
||||
"插件加载错误",
|
||||
"请在%s.py全局指定className值." % mod)
|
||||
return False
|
||||
# 如果是替换对象需求 ,和初始化
|
||||
|
||||
# 实例化类
|
||||
pluginObject = pluginClass(self.__mw)
|
||||
pluginObject.setObjectName(mod)
|
||||
|
||||
self.pluginsInfo["StartModule"][mod]["active"] = True
|
||||
self.pluginsInfo["StartModule"][mod]["pluginClass"] = pluginClass
|
||||
self.pluginsInfo["StartModule"][mod]["parent"] = pluginObject.parent()
|
||||
|
||||
if not NeedRplace:
|
||||
#TODO:其他接口
|
||||
layout = pluginObject.getParentLayout()
|
||||
layout.addWidget(pluginObject)
|
||||
|
||||
self.pluginsInfo["StartModule"][mod]["layout"] = layout
|
||||
self.pluginsInfo["StartModule"][mod]["old"] = pluginObject
|
||||
else:
|
||||
self.pluginsInfo["StartModule"][mod]["new"] = pluginObject
|
||||
return pluginObject
|
||||
# 卸载插件
|
||||
def unload(self, mod: "str"):
|
||||
"""
|
||||
卸载插件 , 移除模块.
|
||||
"""
|
||||
if mod in sys.modules:
|
||||
self.pluginsInfo["StartModule"][mod]["active"] = False
|
||||
#删除对象
|
||||
objInfo = self.findOldObj(mod)
|
||||
oldObj, layout = objInfo["oldObj"], objInfo["layout"]
|
||||
print(oldObj.objectName()+" be unload")
|
||||
|
||||
sip.delete(oldObj)
|
||||
|
||||
# layout.removeWidget(oldObj)
|
||||
self.pluginsInfo["StartModule"][mod]["old"] = None
|
||||
sys.modules.pop(mod)
|
||||
|
||||
return True
|
||||
|
||||
# 重载插件
|
||||
def reload(self, mod):
|
||||
if mod in sys.modules:
|
||||
#TODO: 旧对象替换
|
||||
print("reload")
|
||||
moduleObj = sys.modules[mod]
|
||||
button = QPushButton("哈哈")
|
||||
objInfo = self.findOldObj(mod, moduleObj = moduleObj , needRplace = True)
|
||||
oldObj, newObj, layout = objInfo["oldObj"], objInfo["newObj"], objInfo["layout"]
|
||||
|
||||
print(layout.replaceWidget(oldObj, newObj ))
|
||||
self.pluginsInfo["StartModule"][mod]["old"] = newObj
|
||||
print(self.pluginsInfo["StartModule"][mod])
|
||||
sip.delete(oldObj)
|
||||
else:
|
||||
self.load(mod)
|
||||
|
||||
def findOldObj(self, mod, moduleObj=None, needRplace = False):
|
||||
"""
|
||||
找到需要删除或替换的对象.
|
||||
"""
|
||||
oldObj = self.pluginsInfo["StartModule"][mod]["old"]
|
||||
parentWidget = self.pluginsInfo["StartModule"][mod]["parent"]
|
||||
layout = self.pluginsInfo["StartModule"][mod]["layout"]
|
||||
pluginClass = self.pluginsInfo["StartModule"][mod]["pluginClass"]
|
||||
if needRplace:
|
||||
if moduleObj==None:
|
||||
QMessageBox.information(self.__mw,
|
||||
"错误",
|
||||
"请传入moduleObj值.")
|
||||
else:
|
||||
newObj = self.instantiation(mod, moduleObj, needRplace)
|
||||
else:
|
||||
newObj = None
|
||||
|
||||
return {"oldObj" :oldObj ,
|
||||
"newObj" :newObj ,
|
||||
"parentWidget":parentWidget,
|
||||
"layout" :layout,
|
||||
"pluginClass" :pluginClass,
|
||||
}
|
||||
|
||||
# 卸载所有插件
|
||||
def unloadAll(self):
|
||||
pass
|
||||
|
||||
def PluginToInterFace(self):
|
||||
pass
|
|
@ -1,256 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os , time , imp
|
||||
from copy import deepcopy
|
||||
from importlib.machinery import SourceFileLoader
|
||||
|
||||
|
||||
from PyQt5.QtCore import *
|
||||
from PyQt5.QtGui import *
|
||||
from PyQt5.QtWidgets import *
|
||||
|
||||
from PluginManager import PluginStore
|
||||
|
||||
from Tools.pmf_myjson import *
|
||||
|
||||
"setting_flie -> From Tools.pmf_myjson , json写入的位置"
|
||||
|
||||
class PluginManager(QObject):
|
||||
|
||||
def __init__(self, parent = None , *args, **kwargs):
|
||||
super(PluginManager, self).__init__(parent , *args, **kwargs)
|
||||
self.__mw = parent
|
||||
self.__initUI()
|
||||
|
||||
self.pluginDirs = {"pluginPath": os.path.join("./", "Plugins"),}
|
||||
|
||||
self.header = ["PlugName",
|
||||
"Allow" , "CreateTime", "ModifyTime"]
|
||||
|
||||
self.changePlugin = {
|
||||
"StartModule" :{},
|
||||
"NewModule" :None,
|
||||
"Load" :{},
|
||||
"del" :set(),
|
||||
"rename" :[],
|
||||
}
|
||||
# self.existPlugin :{插件名:{header参数}}
|
||||
# self.pluginsModule :{插件名:{path:插件路径}}
|
||||
|
||||
self.existPlugin, self.pluginsModule = None, None
|
||||
self.existPlugin, self.pluginsModule = \
|
||||
self.getPluginModules(self.pluginDirs['pluginPath'])
|
||||
# print("existPlugin:", self.existPlugin,"\n",
|
||||
# "pluginsModule:", self.pluginsModule)
|
||||
|
||||
#载入模块
|
||||
self.loadAll()
|
||||
|
||||
# 文件监听器
|
||||
|
||||
self.model = QFileSystemModel()
|
||||
self.model.setRootPath("./Plugins")
|
||||
self.model.setFilter( QDir.Files )
|
||||
self.model.setNameFilters(["Plugin*.py"])
|
||||
index = self.model.index("./Plugins")
|
||||
print(self.model.size(index))
|
||||
self.model.setNameFilterDisables(False);
|
||||
|
||||
self.model.rowsRemoved.connect(self.m_rowsRemoved)
|
||||
self.model.directoryLoaded.connect(lambda :self.model.size(index) )
|
||||
|
||||
self.tree = QTreeView()
|
||||
self.tree.setModel(self.model)
|
||||
self.tree.setRootIndex(index);
|
||||
self.tree.show()
|
||||
def m_rowsRemoved(self, index,first, last):
|
||||
print(index)
|
||||
# print(self.model.size())
|
||||
# self.watcher = QFileSystemWatcher(
|
||||
# ["./Plugins"],
|
||||
# directoryChanged = self.m_directoryChanged
|
||||
# )
|
||||
|
||||
def m_directoryChanged(self):
|
||||
self.existPlugin, self.pluginsModule = \
|
||||
self.getPluginModules(self.pluginDirs['pluginPath'], True)
|
||||
|
||||
del self.changePlugin["NewModule"]
|
||||
self.changePlugin["NewModule"] = deepcopy(self.pluginsModule)
|
||||
|
||||
StartModuleLen = len(self.changePlugin["StartModule"])
|
||||
NewModuleLen = len(self.changePlugin["NewModule"])
|
||||
LoadLen = len(self.changePlugin["Load"])
|
||||
|
||||
NewSucModuleLen = NewModuleLen \
|
||||
- StartModuleLen \
|
||||
- LoadLen
|
||||
|
||||
|
||||
if NewSucModuleLen>0:
|
||||
|
||||
moduleSet = set(self.changePlugin["NewModule"]) \
|
||||
- set(self.changePlugin["StartModule"])\
|
||||
- set(self.changePlugin["Load"]) \
|
||||
|
||||
module = moduleSet.pop()
|
||||
|
||||
if not self.load(module):
|
||||
self.changePlugin["Load"]["Success"] = False
|
||||
else:
|
||||
self.changePlugin["Load"]["Success"] = True
|
||||
|
||||
elif NewSucModuleLen<0:
|
||||
pass
|
||||
|
||||
def __initUI(self):
|
||||
if self.__mw.findChild(QMenuBar, "menuBar"):
|
||||
|
||||
self.__mw.menuPlugin = QAction("Plugin", self.__mw.menuBar,
|
||||
triggered = self.__createPluginStoreDialog)
|
||||
self.__mw.menuBar.addAction(self.__mw.menuPlugin)
|
||||
|
||||
else:
|
||||
QMessageBox.information(self.__mw, "", "主窗体没有菜单栏, 请先创建.")
|
||||
|
||||
def __createPluginStoreDialog(self):
|
||||
"""
|
||||
显示插件加载情况的 窗体.
|
||||
"""
|
||||
dia = PluginStore.PluginStore(self, self.__mw)
|
||||
|
||||
dia.exec_()
|
||||
|
||||
def getPluginModules(self, pluginPath:"./Plugins" , CHANGE=False)->"FoJson":
|
||||
|
||||
"""
|
||||
Public method to get a list of plugin modules.
|
||||
"""
|
||||
try:
|
||||
existPlugin = mfunc_readJson(setting_flie)
|
||||
|
||||
except:
|
||||
existPlugin=None
|
||||
|
||||
pluginFiles = {} if CHANGE is False else self.pluginsModule
|
||||
|
||||
for f in os.listdir(pluginPath):
|
||||
# 插件名称的有效性检查
|
||||
if f.endswith(".py") and f.startswith("Plugin"):
|
||||
# 去掉后缀 , 加入模块
|
||||
module = f[:-3]
|
||||
|
||||
fullPath = os.path.join( pluginPath , f)
|
||||
# 增删改的变化
|
||||
if module not in self.changePlugin["StartModule"]:
|
||||
pluginFiles[module] = {"path" :fullPath}
|
||||
|
||||
if "active" not in pluginFiles[module]:
|
||||
pluginFiles[module]["active"] = False
|
||||
print("---" , )
|
||||
# 判断模块不在json文件中
|
||||
if module not in existPlugin:
|
||||
self.addJson(fullPath, module)
|
||||
|
||||
self.delJson(existPlugin, pluginFiles)
|
||||
|
||||
if CHANGE is False:
|
||||
self.changePlugin["StartModule"] = deepcopy(pluginFiles)
|
||||
|
||||
return existPlugin, pluginFiles
|
||||
|
||||
def addJson(self, fullPath , module )->"ToJson":
|
||||
# 插件创建时间
|
||||
_ctime = time.localtime(os.stat(fullPath).st_ctime)
|
||||
ctime = time.strftime("%Y-%m-%d-%H:%M:%S",_ctime)
|
||||
# 插件修改时间
|
||||
_mtime = time.localtime(os.stat(fullPath).st_mtime)
|
||||
mtime = time.strftime("%Y-%m-%d-%H:%M:%S",_mtime)
|
||||
|
||||
# 写入配置
|
||||
mfunc_AKrCVJson( module ,
|
||||
{
|
||||
self.header[1]: True, #allow
|
||||
self.header[2]: ctime,#cteateTime
|
||||
self.header[3]: mtime,#modifyTime
|
||||
} ,
|
||||
self = self)
|
||||
|
||||
def delJson(self , existPlugin, pluginFiles)->"ToJson":
|
||||
|
||||
"""
|
||||
删除插件 的json配置.
|
||||
"""
|
||||
# 获取最终json配置
|
||||
# self.existPlugin = mfunc_readJson(setting_flie)
|
||||
# 添加完重新加载一遍看是否有插件删除
|
||||
if existPlugin==None:
|
||||
existPlugin = mfunc_readJson(setting_flie)
|
||||
|
||||
if len(existPlugin)>len(pluginFiles):
|
||||
with open( setting_flie ,'a+' , encoding='utf-8') as f:
|
||||
# 被删除的插件集合
|
||||
delPlugin = set(existPlugin)-set(pluginFiles)
|
||||
for item in delPlugin:
|
||||
existPlugin.pop(item)
|
||||
self.changePlugin["del"]
|
||||
# 写入配置
|
||||
mfunc_reDumpJson(f, existPlugin)
|
||||
|
||||
# 加载所有插件
|
||||
def loadAll(self):
|
||||
for mod in self.existPlugin:
|
||||
if self.existPlugin[mod]["Allow"] \
|
||||
and not self.pluginsModule[mod]["active"]:
|
||||
|
||||
try:
|
||||
self.load(mod)
|
||||
except:
|
||||
continue
|
||||
|
||||
# 加载插件
|
||||
def load(self , mod:"str"):
|
||||
|
||||
try:
|
||||
# print(self.pluginsModule[mod]["path"])
|
||||
# python内置函数, 把.py 当做模块载入
|
||||
_pluginModule = SourceFileLoader( mod ,
|
||||
self.pluginsModule[mod]["path"]).load_module()
|
||||
# _pluginModule=imp.load_source(mod, self.pluginsModule[mod]["path"])
|
||||
except:
|
||||
# QMessageBox.information(self.__mw,
|
||||
# "模块导入异常",
|
||||
# "请在%s.py检查模块."%mod)
|
||||
|
||||
self.pluginsModule[mod]["active"] = False
|
||||
return False
|
||||
|
||||
try:
|
||||
className = getattr(_pluginModule, "className")
|
||||
pluginClass = getattr(_pluginModule, className )
|
||||
except:
|
||||
self.pluginsModule[mod]["active"] = False
|
||||
QMessageBox.information(self.__mw,
|
||||
"插件加载错误",
|
||||
"请在%s.py全局指定className值."%mod)
|
||||
return False
|
||||
# 实例化类
|
||||
pluginObject = pluginClass()
|
||||
pluginObject.setObjectName(className)
|
||||
|
||||
self.__mw.verticalLayout.addWidget(pluginObject)
|
||||
self.pluginsModule[mod]["active"] = True
|
||||
|
||||
return True
|
||||
# 卸载插件
|
||||
def unload(self, mod:"str"):
|
||||
# self.__mw.findchild()
|
||||
print(sys.modules[mod], mod)
|
||||
print(self.__mw.findChild(QWidget, mod))
|
||||
#TODO:
|
||||
return True
|
||||
|
||||
# 卸载所有插件
|
||||
def unloadAll(self):
|
||||
pass
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
"""
|
||||
管理插件的加载 , 卸载 , 监控文件的添加/删除.
|
||||
"""
|
||||
import os, time, sys , importlib, sip
|
||||
import os, time, sys , importlib, sip, traceback
|
||||
# ==添加插件的搜索路径==
|
||||
#__file__ 为此文件路径 , 在ipython里是测不出来的
|
||||
pluginsManagerPath = os.path.dirname(os.path.abspath(__file__))
|
||||
|
@ -62,10 +62,10 @@ class PluginManager(QObject):
|
|||
mw = self.__mw
|
||||
if mw.findChild(QMenuBar, "menuBar"):
|
||||
# 插入到mainwindow的menuBar下 , 点击查看弹出插件加载情况窗体===
|
||||
mw.menuPlugin = QAction("Plugin", self.__mw.menuBar,
|
||||
mw.menuPlugin = QAction("Plugin", mw.menuBar,
|
||||
triggered=self.__createPluginStoreDialog)
|
||||
|
||||
mw.menuBar.addAction(self.__mw.menuPlugin)
|
||||
mw.menuBar.addAction(mw.menuPlugin)
|
||||
|
||||
else:
|
||||
QMessageBox.information(mw, "", "主窗体没有菜单栏, 请先创建.")
|
||||
|
@ -156,16 +156,16 @@ class PluginManager(QObject):
|
|||
fullPath = os.path.join(pluginFolder, f)
|
||||
|
||||
pluginInfo[module] = {"path": fullPath}
|
||||
try:
|
||||
|
||||
if module not in jsonPlugin:
|
||||
self.addJson(fullPath, module)
|
||||
except:
|
||||
self.addJson(fullPath, module)
|
||||
module, data = self.addJson(fullPath, module)
|
||||
jsonPlugin[module]=data
|
||||
|
||||
|
||||
if CHANGE is False:
|
||||
self.pluginsInfo["StartModule"] = deepcopy(pluginInfo)
|
||||
|
||||
jsonPlugin = self.delJson(jsonPlugin, pluginInfo)
|
||||
jsonPlugin = self.delJson({}, pluginInfo)
|
||||
|
||||
# print("jsonPlugin",jsonPlugin, "\n", "pluginInfo",pluginInfo )
|
||||
|
||||
|
@ -238,7 +238,7 @@ class PluginManager(QObject):
|
|||
_pluginModule = importlib.import_module(mod)
|
||||
|
||||
except:
|
||||
import traceback
|
||||
|
||||
errmsg = traceback.format_exc()
|
||||
|
||||
QMessageBox.information(self.__mw,
|
||||
|
@ -264,26 +264,34 @@ class PluginManager(QObject):
|
|||
className = getattr(moduleObj, "className")
|
||||
pluginClass = getattr(moduleObj, className )
|
||||
except:
|
||||
self.pluginsInfo[mod]["active"] = False
|
||||
self.pluginsInfo["StartModule"][mod]["active"] = False
|
||||
errmsg = traceback.format_exc()
|
||||
QMessageBox.information(self.__mw,
|
||||
"插件加载错误",
|
||||
"请在%s.py全局指定className值." % mod)
|
||||
"%s ,请在%s.py全局指定className值." % (errmsg, mod))
|
||||
return False
|
||||
# 如果是替换对象需求 ,和初始化
|
||||
|
||||
# 实例化类
|
||||
try:
|
||||
pluginObject = pluginClass(self.__mw)
|
||||
pluginObject.setObjectName(mod)
|
||||
|
||||
self.pluginsInfo["StartModule"][mod]["active"] = True
|
||||
self.pluginsInfo["StartModule"][mod]["pluginClass"] = pluginClass
|
||||
self.pluginsInfo["StartModule"][mod]["parent"] = pluginObject.parent()
|
||||
except:
|
||||
|
||||
self.pluginsInfo["StartModule"][mod]["active"] = False
|
||||
errmsg = traceback.format_exc()
|
||||
QMessageBox.information(self.__mw,
|
||||
"插件加载错误",
|
||||
"%s ,请在%s.py全局指定className值." % (errmsg, mod))
|
||||
|
||||
if not NeedRplace:
|
||||
#TODO:其他接口
|
||||
layout = pluginObject.getParentLayout()
|
||||
layout.addWidget(pluginObject)
|
||||
|
||||
pluginObject.toInterface()
|
||||
self.pluginsInfo["StartModule"][mod]["layout"] = layout
|
||||
self.pluginsInfo["StartModule"][mod]["old"] = pluginObject
|
||||
else:
|
||||
|
@ -300,8 +308,15 @@ class PluginManager(QObject):
|
|||
print("reload")
|
||||
importlib.reload(sys.modules[mod])
|
||||
moduleObj = sys.modules[mod]
|
||||
|
||||
try:
|
||||
objInfo = self.findOldObj(mod, moduleObj , True)
|
||||
except:
|
||||
errmsg = traceback.format_exc()
|
||||
|
||||
QMessageBox.information(self.__mw,
|
||||
"模块导入异常",
|
||||
"%s,请在%s.py检查模块."%(errmsg,mod ))
|
||||
|
||||
oldObj, newObj, layout = objInfo["oldObj"],\
|
||||
objInfo["newObj"],\
|
||||
objInfo["layout"]
|
||||
|
@ -309,7 +324,7 @@ class PluginManager(QObject):
|
|||
# 新对象替换旧对象 , 并把地址赋值给旧对象
|
||||
layout.replaceWidget(oldObj, newObj )
|
||||
self.pluginsInfo["StartModule"][mod]["old"] = newObj
|
||||
|
||||
oldObj.flag="reload"
|
||||
sip.delete(oldObj)
|
||||
else:
|
||||
self.load(mod)
|
||||
|
@ -352,7 +367,7 @@ class PluginManager(QObject):
|
|||
#删除对象
|
||||
objInfo = self.findOldObj(mod)
|
||||
oldObj = objInfo["oldObj"]
|
||||
|
||||
oldObj.flag="unload"
|
||||
sip.delete(oldObj)
|
||||
|
||||
self.pluginsInfo["StartModule"][mod]["old"] = None
|
||||
|
|
|
@ -117,7 +117,6 @@ class PluginStore(QDialog, Ui_Dialog):
|
|||
if msg==QMessageBox.Yes:
|
||||
self.manager.unload(mod)
|
||||
else:
|
||||
|
||||
self.manager.reload(mod)
|
||||
|
||||
# 右键菜单重载和卸载 , 默认的是选行的第0列
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
|
||||
#import sys, os
|
||||
#pluginsManagetPath = os.path.dirname(os.path.abspath(__file__))
|
||||
#mainPath = os.path.dirname(pluginsManagetPath)
|
||||
#pluginsPath = os.path.join(pluginsManagetPath, "Plugins")
|
||||
#
|
||||
#for i in [pluginsPath]:
|
||||
# print(mainPath, pluginsManagetPath, pluginsPath)
|
||||
# sys.path.insert(0, i)
|
||||
# print("add")
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
插件的加载 , 重载 , 卸载模块 , 配置文件模块.
|
||||
"""
|
||||
|
|
|
@ -1,17 +1,32 @@
|
|||
{
|
||||
"PluginPage1": {
|
||||
"Allow": false,
|
||||
"PluginPage0_inMainLayout": {
|
||||
"Allow": true,
|
||||
"CreateTime": "2018-09-18-18:44:18",
|
||||
"ModifyTime": "2018-09-23-20:13:56"
|
||||
"ModifyTime": "2018-09-24-15:58:45"
|
||||
},
|
||||
"PluginPage2": {
|
||||
"PluginPage1_addTab3": {
|
||||
"Allow": true,
|
||||
"CreateTime": "2018-09-24-17:48:29",
|
||||
"ModifyTime": "2018-09-24-18:24:48"
|
||||
},
|
||||
"PluginPage1_addTab4": {
|
||||
"Allow": true,
|
||||
"CreateTime": "2018-09-24-18:17:19",
|
||||
"ModifyTime": "2018-09-24-18:24:22"
|
||||
},
|
||||
"PluginPage2_error": {
|
||||
"Allow": false,
|
||||
"CreateTime": "2018-09-18-18:45:14",
|
||||
"ModifyTime": "2018-09-19-18:16:08"
|
||||
},
|
||||
"Pluginmmm": {
|
||||
"PluginPage3_addAction2": {
|
||||
"Allow": true,
|
||||
"CreateTime": "2018-09-23-20:57:37",
|
||||
"ModifyTime": "2018-09-23-20:13:56"
|
||||
"CreateTime": "2018-09-24-20:54:48",
|
||||
"ModifyTime": "2018-09-24-20:57:03"
|
||||
},
|
||||
"PluginPage3_addAction1": {
|
||||
"Allow": true,
|
||||
"CreateTime": "2018-09-24-18:26:10",
|
||||
"ModifyTime": "2018-09-24-20:50:02"
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Project SYSTEM "Project-6.0.dtd">
|
||||
<!-- eric project file for project Plugins -->
|
||||
<!-- Saved: 2018-09-21, 22:53:13 -->
|
||||
<!-- Saved: 2018-09-24, 21:05:10 -->
|
||||
<!-- Copyright (C) 2018 , -->
|
||||
<Project version="6.0">
|
||||
<Language></Language>
|
||||
|
@ -17,10 +17,14 @@
|
|||
<Source>PluginManager/PluginStore/PluginStore.py</Source>
|
||||
<Source>PluginManager/PluginStore/StoreModel.py</Source>
|
||||
<Source>PluginManager/PluginStore/Ui_PluginStore.py</Source>
|
||||
<Source>PluginManager/PluginStore/__init__.py</Source>
|
||||
<Source>PluginManager/__init__.py</Source>
|
||||
<Source>Plugins/PluginPage1.py</Source>
|
||||
<Source>Plugins/PluginPage2.py</Source>
|
||||
<Source>Plugins/Pluginmmm.py</Source>
|
||||
<Source>Plugins/PluginPage0_inMainLayout.py</Source>
|
||||
<Source>Plugins/PluginPage1_addTab3.py</Source>
|
||||
<Source>Plugins/PluginPage1_addTab4.py</Source>
|
||||
<Source>Plugins/PluginPage2_error.py</Source>
|
||||
<Source>Plugins/PluginPage3_addAction1.py</Source>
|
||||
<Source>Plugins/PluginPage3_addAction2.py</Source>
|
||||
<Source>Plugins/__init__.py</Source>
|
||||
<Source>Plugins/page1/Ui_PluginPage1.py</Source>
|
||||
<Source>Plugins/page1/__init__.py</Source>
|
||||
|
@ -38,6 +42,9 @@
|
|||
<Form>Plugins/page2/PluginPage2.ui</Form>
|
||||
<Form>main.ui</Form>
|
||||
</Forms>
|
||||
<Others>
|
||||
<Other>Documentation</Other>
|
||||
</Others>
|
||||
<MainScript>main.py</MainScript>
|
||||
<Vcs>
|
||||
<VcsType>None</VcsType>
|
||||
|
@ -60,4 +67,59 @@
|
|||
<FiletypeAssociation pattern="README" type="OTHERS"/>
|
||||
<FiletypeAssociation pattern="README.*" type="OTHERS"/>
|
||||
</FiletypeAssociations>
|
||||
<Documentation>
|
||||
<DocumentationParams>
|
||||
<dict>
|
||||
<key>
|
||||
<string>ERIC4DOC</string>
|
||||
</key>
|
||||
<value>
|
||||
<dict>
|
||||
<key>
|
||||
<string>cssFile</string>
|
||||
</key>
|
||||
<value>
|
||||
<string>%PYTHON%/eric6/CSSs/default.css</string>
|
||||
</value>
|
||||
<key>
|
||||
<string>ignoreDirectories</string>
|
||||
</key>
|
||||
<value>
|
||||
<list>
|
||||
<string>page1</string>
|
||||
<string>page2</string>
|
||||
</list>
|
||||
</value>
|
||||
<key>
|
||||
<string>ignoreFilePatterns</string>
|
||||
</key>
|
||||
<value>
|
||||
<list>
|
||||
<string>Ui*.py</string>
|
||||
<string>Plugins\\*Page*.py</string>
|
||||
</list>
|
||||
</value>
|
||||
<key>
|
||||
<string>outputDirectory</string>
|
||||
</key>
|
||||
<value>
|
||||
<string>Documentation</string>
|
||||
</value>
|
||||
<key>
|
||||
<string>qtHelpEnabled</string>
|
||||
</key>
|
||||
<value>
|
||||
<bool>False</bool>
|
||||
</value>
|
||||
<key>
|
||||
<string>useRecursion</string>
|
||||
</key>
|
||||
<value>
|
||||
<bool>True</bool>
|
||||
</value>
|
||||
</dict>
|
||||
</value>
|
||||
</dict>
|
||||
</DocumentationParams>
|
||||
</Documentation>
|
||||
</Project>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Module implementing Form.
|
||||
插件例子1.
|
||||
"""
|
||||
|
||||
"""
|
||||
|
@ -14,8 +14,6 @@ site: https://github.com/625781186 <br>
|
|||
视频教程: https://space.bilibili.com/1863103/#/ <br>
|
||||
"""
|
||||
|
||||
|
||||
|
||||
from PyQt5 import QtGui, QtWidgets, QtCore
|
||||
from PyQt5.QtCore import *
|
||||
from PyQt5.QtGui import *
|
||||
|
@ -27,6 +25,7 @@ try:
|
|||
except:
|
||||
from page1.Ui_PluginPage1 import Ui_Form
|
||||
|
||||
# 实例化类名, 必须
|
||||
className = "Form"
|
||||
|
||||
class Form(QWidget, Ui_Form):
|
||||
|
@ -35,10 +34,7 @@ class Form(QWidget, Ui_Form):
|
|||
"""
|
||||
def __init__(self, parent=None):
|
||||
"""
|
||||
Constructor
|
||||
|
||||
@param parent reference to the parent widget
|
||||
@type QWidget
|
||||
"""
|
||||
super(Form, self).__init__(parent)
|
||||
self.setupUi(self)
|
||||
|
@ -46,8 +42,18 @@ class Form(QWidget, Ui_Form):
|
|||
# layout = self.getParentLayout()
|
||||
# layout.addWidget(self)
|
||||
def getParentLayout(self):
|
||||
"""
|
||||
布局函数,必须.
|
||||
"""
|
||||
return self.__mw.verticalLayout
|
||||
|
||||
def toInterface(self):
|
||||
"""
|
||||
插入到界面,必须
|
||||
"""
|
||||
layout = self.getParentLayout()
|
||||
layout.addWidget(self)
|
||||
|
||||
def __del__(self):
|
||||
print("die")
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Module implementing Form.
|
||||
"""
|
||||
|
||||
"""
|
||||
Created on 2018-09-18 <br>
|
||||
description: $description$ <br>
|
||||
author: 625781186@qq.com <br>
|
||||
site: https://github.com/625781186 <br>
|
||||
更多经典例子:https://github.com/892768447/PyQt <br>
|
||||
课件: https://github.com/625781186/WoHowLearn_PyQt5 <br>
|
||||
视频教程: https://space.bilibili.com/1863103/#/ <br>
|
||||
"""
|
||||
|
||||
from PyQt5 import QtGui, QtWidgets, QtCore
|
||||
from PyQt5.QtCore import *
|
||||
from PyQt5.QtGui import *
|
||||
from PyQt5.QtWidgets import *
|
||||
|
||||
from PyQt5.QtWidgets import QWidget
|
||||
|
||||
from Plugin..Ui_PluginPage2 import Ui_Form
|
||||
|
||||
|
||||
className = "Form"
|
||||
|
||||
class Form(QWidget, Ui_Form):
|
||||
"""
|
||||
Class documentation goes here.
|
||||
"""
|
||||
def __init__(self, parent=None):
|
||||
"""
|
||||
Constructor
|
||||
|
||||
@param parent reference to the parent widget
|
||||
@type QWidget
|
||||
"""
|
||||
super(Form, self).__init__(parent)
|
||||
self.setupUi(self)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
app.setStyle(QStyleFactory.create("Fusion"))
|
||||
|
||||
# 自定义CSS样式
|
||||
# from BasePack.CommonHelper import CommonHelper
|
||||
# styleFile = 'BasePack/style.css'
|
||||
# qssStyle = CommonHelper.readQss( styleFile )
|
||||
# framelessWindow.setStyleSheet( qssStyle )
|
||||
|
||||
# If you want to use this style, please pip install qdarkstyle.
|
||||
# import qdarkstyle
|
||||
# app.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())
|
||||
|
||||
ui = Form()
|
||||
|
||||
ui.show()
|
||||
sys.exit(app.exec_())
|
|
@ -1,87 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Module implementing Form.
|
||||
"""
|
||||
|
||||
"""
|
||||
Created on 2018-09-18 <br>
|
||||
description: $description$ <br>
|
||||
author: 625781186@qq.com <br>
|
||||
site: https://github.com/625781186 <br>
|
||||
更多经典例子:https://github.com/892768447/PyQt <br>
|
||||
课件: https://github.com/625781186/WoHowLearn_PyQt5 <br>
|
||||
视频教程: https://space.bilibili.com/1863103/#/ <br>
|
||||
"""
|
||||
|
||||
|
||||
|
||||
from PyQt5 import QtGui, QtWidgets, QtCore
|
||||
from PyQt5.QtCore import *
|
||||
from PyQt5.QtGui import *
|
||||
from PyQt5.QtWidgets import *
|
||||
|
||||
from PyQt5.QtWidgets import QWidget
|
||||
try:
|
||||
from Ui_PluginPage1 import Ui_Form
|
||||
except:
|
||||
from page1.Ui_PluginPage1 import Ui_Form
|
||||
|
||||
className = "Form"
|
||||
|
||||
class Form(QWidget, Ui_Form):
|
||||
"""
|
||||
Class documentation goes here.
|
||||
"""
|
||||
def __init__(self, parent=None):
|
||||
"""
|
||||
Constructor
|
||||
|
||||
@param parent reference to the parent widget
|
||||
@type QWidget
|
||||
"""
|
||||
super(Form, self).__init__(parent)
|
||||
self.setupUi(self)
|
||||
self.__mw = parent
|
||||
|
||||
|
||||
def __del__(self):
|
||||
print("die")
|
||||
|
||||
@pyqtSlot()
|
||||
def on_pushButton_clicked(self):
|
||||
|
||||
print(15111)
|
||||
pass
|
||||
@pyqtSlot()
|
||||
def on_pushButton_2_clicked(self):
|
||||
|
||||
print(222)
|
||||
pass
|
||||
@pyqtSlot()
|
||||
def on_pushButton_3_clicked(self):
|
||||
|
||||
print(333)
|
||||
pass
|
||||
def getParentLayout(self):
|
||||
return self.__mw.verticalLayout
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
app.setStyle(QStyleFactory.create("Fusion"))
|
||||
|
||||
# 自定义CSS样式
|
||||
# from BasePack.CommonHelper import CommonHelper
|
||||
# styleFile = 'BasePack/style.css'
|
||||
# qssStyle = CommonHelper.readQss( styleFile )
|
||||
# framelessWindow.setStyleSheet( qssStyle )
|
||||
|
||||
# If you want to use this style, please pip install qdarkstyle.
|
||||
# import qdarkstyle
|
||||
# app.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())
|
||||
|
||||
ui = Form()
|
||||
|
||||
ui.show()
|
||||
sys.exit(app.exec_())
|
|
@ -0,0 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
插件搜索目录.
|
||||
"""
|
|
@ -0,0 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
增删改查建json.
|
||||
"""
|
|
@ -1,7 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
初始化json配置函数.
|
||||
增删改查建json.
|
||||
"""
|
||||
from PyQt5.QtWidgets import *
|
||||
from PyQt5.QtWidgets import QMessageBox , QWidget , QApplication
|
||||
|
|
|
@ -11,7 +11,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
|||
class Ui_MainWindow(object):
|
||||
def setupUi(self, MainWindow):
|
||||
MainWindow.setObjectName("MainWindow")
|
||||
MainWindow.resize(510, 379)
|
||||
MainWindow.resize(510, 378)
|
||||
self.centralWidget = QtWidgets.QWidget(MainWindow)
|
||||
self.centralWidget.setObjectName("centralWidget")
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralWidget)
|
||||
|
@ -39,11 +39,44 @@ class Ui_MainWindow(object):
|
|||
self.menuBar.setObjectName("menuBar")
|
||||
self.menuFile = QtWidgets.QMenu(self.menuBar)
|
||||
self.menuFile.setObjectName("menuFile")
|
||||
self.menuOpen_Recent_Files = QtWidgets.QMenu(self.menuFile)
|
||||
self.menuOpen_Recent_Files.setObjectName("menuOpen_Recent_Files")
|
||||
self.menufile1 = QtWidgets.QMenu(self.menuOpen_Recent_Files)
|
||||
self.menufile1.setObjectName("menufile1")
|
||||
self.menufile11 = QtWidgets.QMenu(self.menufile1)
|
||||
self.menufile11.setObjectName("menufile11")
|
||||
self.menuEdit = QtWidgets.QMenu(self.menuBar)
|
||||
self.menuEdit.setObjectName("menuEdit")
|
||||
self.menuView = QtWidgets.QMenu(self.menuBar)
|
||||
self.menuView.setObjectName("menuView")
|
||||
MainWindow.setMenuBar(self.menuBar)
|
||||
self.actionadd1 = QtWidgets.QAction(MainWindow)
|
||||
self.actionadd1.setObjectName("actionadd1")
|
||||
self.actionsave = QtWidgets.QAction(MainWindow)
|
||||
self.actionsave.setObjectName("actionsave")
|
||||
self.actionOpen = QtWidgets.QAction(MainWindow)
|
||||
self.actionOpen.setObjectName("actionOpen")
|
||||
self.actionfile2 = QtWidgets.QAction(MainWindow)
|
||||
self.actionfile2.setObjectName("actionfile2")
|
||||
self.actionfile3 = QtWidgets.QAction(MainWindow)
|
||||
self.actionfile3.setObjectName("actionfile3")
|
||||
self.actionfile11 = QtWidgets.QAction(MainWindow)
|
||||
self.actionfile11.setObjectName("actionfile11")
|
||||
self.actionfile22 = QtWidgets.QAction(MainWindow)
|
||||
self.actionfile22.setObjectName("actionfile22")
|
||||
self.actionfile111 = QtWidgets.QAction(MainWindow)
|
||||
self.actionfile111.setObjectName("actionfile111")
|
||||
self.menufile11.addAction(self.actionfile111)
|
||||
self.menufile1.addAction(self.menufile11.menuAction())
|
||||
self.menufile1.addAction(self.actionfile22)
|
||||
self.menuOpen_Recent_Files.addAction(self.menufile1.menuAction())
|
||||
self.menuOpen_Recent_Files.addAction(self.actionfile2)
|
||||
self.menuOpen_Recent_Files.addAction(self.actionfile3)
|
||||
self.menuFile.addAction(self.actionadd1)
|
||||
self.menuFile.addAction(self.actionsave)
|
||||
self.menuFile.addAction(self.actionOpen)
|
||||
self.menuFile.addSeparator()
|
||||
self.menuFile.addAction(self.menuOpen_Recent_Files.menuAction())
|
||||
self.menuBar.addAction(self.menuFile.menuAction())
|
||||
self.menuBar.addAction(self.menuEdit.menuAction())
|
||||
self.menuBar.addAction(self.menuView.menuAction())
|
||||
|
@ -60,8 +93,19 @@ class Ui_MainWindow(object):
|
|||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Tab 1"))
|
||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Tab 2"))
|
||||
self.menuFile.setTitle(_translate("MainWindow", "File"))
|
||||
self.menuOpen_Recent_Files.setTitle(_translate("MainWindow", "Open Recent Files"))
|
||||
self.menufile1.setTitle(_translate("MainWindow", "file1"))
|
||||
self.menufile11.setTitle(_translate("MainWindow", "file11"))
|
||||
self.menuEdit.setTitle(_translate("MainWindow", "Edit"))
|
||||
self.menuView.setTitle(_translate("MainWindow", "View"))
|
||||
self.actionadd1.setText(_translate("MainWindow", "New Window"))
|
||||
self.actionsave.setText(_translate("MainWindow", "New"))
|
||||
self.actionOpen.setText(_translate("MainWindow", "Open"))
|
||||
self.actionfile2.setText(_translate("MainWindow", "file2"))
|
||||
self.actionfile3.setText(_translate("MainWindow", "file3"))
|
||||
self.actionfile11.setText(_translate("MainWindow", "file11"))
|
||||
self.actionfile22.setText(_translate("MainWindow", "file22"))
|
||||
self.actionfile111.setText(_translate("MainWindow", "file111"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Module implementing MainWindow.
|
||||
主函数入口.
|
||||
"""
|
||||
|
||||
"""
|
||||
|
@ -13,7 +13,7 @@ site: https://github.com/625781186 <br>
|
|||
课件: https://github.com/625781186/WoHowLearn_PyQt5 <br>
|
||||
视频教程: https://space.bilibili.com/1863103/#/ <br>
|
||||
"""
|
||||
import os, time, imp, sys
|
||||
import sys
|
||||
|
||||
|
||||
from PyQt5 import QtGui, QtWidgets, QtCore
|
||||
|
@ -48,20 +48,21 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
"""
|
||||
print(sys.path)
|
||||
pass
|
||||
|
||||
def closeEvent(self, e):
|
||||
self.pluginManager.dia.close()
|
||||
if __name__ == "__main__":
|
||||
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
app.setStyle(QStyleFactory.create("Fusion"))
|
||||
|
||||
# def excepthook(type, value, trace):
|
||||
# try:
|
||||
# pass
|
||||
# except :
|
||||
# pass
|
||||
# sys.__excepthook__(type, value, trace)
|
||||
def excepthook(type, value, trace):
|
||||
try:
|
||||
pass
|
||||
except :
|
||||
pass
|
||||
sys.__excepthook__(type, value, trace)
|
||||
|
||||
# sys.excepthook = excepthook
|
||||
sys.excepthook = excepthook
|
||||
|
||||
ui = MainWindow()
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>510</width>
|
||||
<height>379</height>
|
||||
<height>378</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -63,6 +63,32 @@
|
|||
<property name="title">
|
||||
<string>File</string>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuOpen_Recent_Files">
|
||||
<property name="title">
|
||||
<string>Open Recent Files</string>
|
||||
</property>
|
||||
<widget class="QMenu" name="menufile1">
|
||||
<property name="title">
|
||||
<string>file1</string>
|
||||
</property>
|
||||
<widget class="QMenu" name="menufile11">
|
||||
<property name="title">
|
||||
<string>file11</string>
|
||||
</property>
|
||||
<addaction name="actionfile111"/>
|
||||
</widget>
|
||||
<addaction name="menufile11"/>
|
||||
<addaction name="actionfile22"/>
|
||||
</widget>
|
||||
<addaction name="menufile1"/>
|
||||
<addaction name="actionfile2"/>
|
||||
<addaction name="actionfile3"/>
|
||||
</widget>
|
||||
<addaction name="actionadd1"/>
|
||||
<addaction name="actionsave"/>
|
||||
<addaction name="actionOpen"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="menuOpen_Recent_Files"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuEdit">
|
||||
<property name="title">
|
||||
|
@ -78,6 +104,46 @@
|
|||
<addaction name="menuEdit"/>
|
||||
<addaction name="menuView"/>
|
||||
</widget>
|
||||
<action name="actionadd1">
|
||||
<property name="text">
|
||||
<string>New Window</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionsave">
|
||||
<property name="text">
|
||||
<string>New</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOpen">
|
||||
<property name="text">
|
||||
<string>Open</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionfile2">
|
||||
<property name="text">
|
||||
<string>file2</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionfile3">
|
||||
<property name="text">
|
||||
<string>file3</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionfile11">
|
||||
<property name="text">
|
||||
<string>file11</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionfile22">
|
||||
<property name="text">
|
||||
<string>file22</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionfile111">
|
||||
<property name="text">
|
||||
<string>file111</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
|
Loading…
Reference in a new issue