前言
本文是《Python插件实现1》的后续,主要介绍UI扩展的实现。
UI扩展
UI是桌面应用程序最重要的模块。UI扩展首先涉及了UI框架的选择,另外还会设计框架内具体UI子框架的选择。本文选择了wxWidgets框架作为Python UI开发的首选框架,没有选择QT的主要原因是,担心未来商业应用的版权问题。在wxWxidgets中,还有对话框,多文档,AUI框架等不同的子框架,本文选择使用AUI作为扩展基础框架,主要原因是AUI的灵活性。
具体实现
APP插件的扩展
APP插件作为应用的入口插件,承载了UI框架的规范设计职责,所以在该插件中定义了可以进行扩展的扩展点,本文提供了两个扩展点,菜单扩展点、面板扩展点。工具条可以看作是一类特殊的面板扩展。
APP插件最终代码如下:
import wx
import wx.grid
import wx.html
import wx.aui as aui
from six import BytesIO
context = None
def init(context_):
global context
context = context_
# MainFrame
class Mywin(wx.Frame):
def __init__(self, parent, title):
super(Mywin, self).__init__(parent, title = title, size = (500,500))
self.mgr = wx.aui.AuiManager(self)
menuBar = wx.MenuBar()
self.SetMenuBar(menuBar)
exts = context.find_extension("PL::Basic::Menu")
for ext in exts:
ext.add_menu(menuBar)
exts = context.find_extension("PL::Basic::Pane")
for ext in exts:
ext.add_pane(self.mgr)
self.mgr.Update()
self.Bind(wx.EVT_CLOSE, self.OnClose)
self.Centre()
self.CreateStatusBar()
self.SetStatusText("This is the statusbar")
def OnClose(self, event):
self.mgr.UnInit()
self.Destroy()
class MyApp:
def name(self):
return "MyApp"
def run(self, argv):
context.fire("Event1", {"id", 20})
exts = context.find_extension("PL::Test1")
for ext in exts:
ext.test()
app = wx.App()
frame = Mywin(None, "ABC")
frame.CenterOnScreen()
frame.Show()
app.MainLoop()
print("Hello in MyAPP!!")
class MyTest:
def test(self):
print("Hello Test!")
class MenuExtension:
def add_menu(self, menu_bar):
print("Hello in add_menu!")
class PaneExtension:
def add_pane(self, auiMgr):
print("Hello in add_pane!")
def HelloServiceFun(a, b):
print("HelloService:", a+b)
config = {
"extensions" : [
{
"name": "PL::APP",
"impl": MyApp()
}
],
"extensions_def" : [
{
"name": "PL::Test1",
"define": MyTest
},
{
"name": "PL::Basic::Menu",
"define": MenuExtension
},
{
"name": "PL::Basic::Pane",
"define": PaneExtension
}
],
"services" : [
{
"name": "HelloService",
"define": HelloServiceFun
}
]
}
插件b的扩展
插件b主要演示如何进行UI扩展点的具体实现。本文中,进行了菜单扩展实现,工具条扩展实现,面板扩展实现。
最终代码如下:
import wx
import wx.grid
import wx.html
import wx.aui as aui
context = None
def init(context_):
global context
context = context_
class MyApp:
def name(self):
return "MyApp"
def run(self, argv):
print("Hello in MyAPP!!")
class MyTest:
def test(self):
print("Hello Test222!")
class MenuExtension:
def add_menu(self, menu_bar):
menu1 = wx.Menu()
menu1.Append(101, "&Mercury", "This the text in the Statusbar")
menu1.Append(102, "&Venus", "")
menu2 = wx.Menu()
menu2.Append(wx.ID_ANY, "Lanthanides", menu1)
menu_bar.Append(menu2, "&Fun11")
class PaneExtension:
def add_pane(self, auiMgr):
text3 = wx.TextCtrl(auiMgr.GetManagedWindow())
auiMgr.AddPane(text3, wx.RIGHT, "Pane Caption222222")
class PaneExtensionNotePane:
def add_pane(self, auiMgr):
text3 = TestPanel(auiMgr.GetManagedWindow())
auiMgr.AddPane(text3, wx.BOTTOM, "Pane Caption222222")
class PaneExtensionToolbar:
def add_pane(self, auiMgr):
tb4 = aui.AuiToolBar(auiMgr.GetManagedWindow())
tb4.SetToolBitmapSize(wx.Size(16, 16))
tb4.AddLabel(-1, "Open")
tb4.AddLabel(-1, "Save")
auiMgr.AddPane(tb4, aui.AuiPaneInfo().Name("tb4").Caption("Sample Bookmark Toolbar").ToolbarPane().Top())
text = """\
Hello!
Welcome to this little demo of draggable tabs using the aui module.
To try it out, drag a tab from the top of the window all the way to the bottom. After releasing the mouse, the tab will dock at the hinted position. Then try it again with the remaining tabs in various other positions. Finally, try dragging a tab to an existing tab ctrl. You'll soon see that very complex tab layouts may be achieved.
"""
class TestPanel(wx.Panel):
def __init__(self, parent):
#self.log = log
wx.Panel.__init__(self, parent, -1)
self.nb = aui.AuiNotebook(self, style=wx.aui.AUI_NB_DEFAULT_STYLE | wx.aui.AUI_NB_TAB_EXTERNAL_MOVE)
page = wx.TextCtrl(self.nb, -1, text, style=wx.TE_MULTILINE)
self.nb.AddPage(page, "Welcome")
for num in range(1, 5):
page = wx.TextCtrl(self.nb, -1, "This is page %d" % num ,
style=wx.TE_MULTILINE)
self.nb.AddPage(page, "Tab Number %d" % num)
sizer = wx.BoxSizer()
sizer.Add(self.nb, 1, wx.EXPAND)
self.SetSizer(sizer)
wx.CallAfter(self.nb.SendSizeEvent)
def MyEventFun(val):
service = context.find_service("HelloService")
if (service):
service(30, 40)
print("MyEventFun:", val)
config = {
"extensions" : [
{
"name": "PL::Test1",
"impl": MyTest()
},
{
"name": "PL::Basic::Menu",
"impl": MenuExtension()
},
{
"name": "PL::Basic::Pane",
"impl": PaneExtension()
},
{
"name": "PL::Basic::Pane",
"impl": PaneExtensionNotePane()
},
{
"name": "PL::Basic::Pane",
"impl": PaneExtensionToolbar()
}
],
"subscribes" : [
{
"name": "Event1",
"define": MyEventFun
}
]
}
UI效果
UI扩展效果图上图中菜单,工具条,面板都是有插件b扩展实现提供。
网友评论