MEP27:将 pyplot 与后端解耦#
状态#
进步
分支和拉取请求#
主要公关(包括 GTK3):
后端特定的分支差异:
摘要#
此 MEP 重构后端以提供更结构化和一致的 API,删除通用代码并整合现有代码。为此,我们建议拆分:
FigureManagerBase
及其派生类分为核心功能类FigureManager
和后端特定类WindowBase
和ShowBase
及其派生类到Gcf.show_all
和MainLoopBase
。
详细说明#
该 MEP 旨在将后端 API 整合到一个统一的 API 中,从后端(包括
_pylab_helpers
和Gcf
)中删除通用代码,并将代码推送到 matplotlib 中更合适的级别。有了这个,我们会自动删除后端中出现的不一致,例如
有时设置画布,有时将整个窗口设置为给定的尺寸,具体取决于后端。FigureManagerBase.resize(w, h)
泛型代码的两个主要位置出现在派生自
FigureManagerBase
和的类中ShowBase
。
FigureManagerBase
目前有三份工作:文档将其描述为 pyplot 模式的 Helper 类,将所有内容打包成一个整洁的包
但它不只是包装画布和工具栏,它本身还执行所有窗口任务。这两个任务的结合在以下行中得到了最好的体现: 这结合了后端特定代码和 matplotlib 通用代码。
self.set_window_title("Figure %d" % num)
self.set_window_title(title)
title = "Figure %d" % num
目前后端特定子类
FigureManager
决定何时结束主循环。这似乎也很错误,因为该数字不应控制其他数字。
ShowBase
有两个工作:它的工作是遍历所有注册的人物经理
_pylab_helpers.Gcf
并告诉他们展示自己。其次,它负责执行特定的后端
mainloop
以阻止主程序,从而防止数字死亡。
实施#
该 MEP 的描述为我们提供了大部分解决方案:
删除窗口方面,
FigureManagerBase
让它简单地将这个新类与其他后端类一起包装。创建一个WindowBase
可以处理此功能的新类,使用传递方法 (:arrow_right:) 到WindowBase
. 子类的类WindowBase
也应该是 GUI 特定窗口类的子类,以确保向后兼容 ( )。manager.window == manager.window
重构 into 的
ShowBase
主MainLoopBase
循环,它也封装了循环的结尾。我们给出一个MainLoop
to的实例FigureManager
作为解锁退出方法的键(要求在循环终止之前返回所有键)。请注意,这为多个后端同时运行提供了可能性。现在它
FigureManagerBase
没有后端细节,将其重命名为FigureManager
,并移动到一个新文件backend_managers.py
,注意:这使我们能够将后端转换为单独的 PR,因为我们可以保持现有
FigureManagerBase
类及其依赖项完好无损。这也预示了 MEP22 中新的
NavigationBase
已经演变成后端独立的ToolManager
.
FigureManagerBase(canvas, num) |
图管理器(图,数字) |
|
笔记 |
---|---|---|---|
节目 |
节目 |
||
破坏 |
对所有组件调用destroy |
破坏 |
|
全屏切换 |
处理逻辑 |
设置全屏 |
|
调整大小 |
调整大小 |
||
按键 |
按键 |
||
获取窗口标题 |
获取窗口标题 |
||
设置窗口标题 |
设置窗口标题 |
||
_get_toolbar |
FigureManagerBase 所有子类的通用方法 |
||
设置默认大小 |
|||
add_element_to_window |
展示基地 |
主循环库 |
笔记 |
---|---|---|
主循环 |
开始 |
|
结尾 |
当不存在子类的更多实例时自动调用 |
|
__称呼__ |
方法移至 Gcf.show_all |
未来的兼容性#
正如上面讨论 MEP 22 时所回避的那样,这种重构使得添加新的通用特性变得容易。目前,MEP 22 必须对从FigureManagerBase
. 使用此代码,只需在单个FigureManager
类中进行。这也使得后面的 deprecation
NavigationToolbar2
非常直接,只需要碰单FigureManager
类
MEP 23 提供了另一个用例,这个重构的代码将非常方便。
向后兼容性#
由于我们保持所有后端代码不变,只向现有类添加缺少的方法,这应该适用于所有用例。由于 API 的标准化,唯一的区别在于用于
FigureManager.resize
调整画布而不是窗口大小的后端。
我会设想这个重构过时的类在与 相同的时间表上被弃用和删除
NavigationToolbar2
,还请注意对FigureCanvasWx
构造函数的调用签名的更改,虽然向后兼容,但我认为旧的(恕我直言丑陋的风格)签名应该被弃用并以与其他所有内容相同的方式删除。
后端 |
manager.resize(w,h) |
额外的 |
---|---|---|
gtk3 |
窗户 |
|
总热量 |
帆布 |
|
Qt |
窗户 |
|
Wx |
帆布 |
FigureManagerWx
|
替代方案#
如果有任何替代解决方案来解决相同的问题,则应在此处对其进行讨论,并说明所选方法的理由。
问题#
Mdehoon:您能否详细说明如何同时运行多个后端?
OceanWolf:@mdehoon,正如我所说,不是为了这个 MEP,但我认为这个 MEP 开启了它作为未来的可能性。基本上,MainLoopBase
该类充当每个后端 Gcf,在此 MEP 中,它跟踪每个后端打开的图形数量,并管理这些后端的主循环。当它检测到后端没有任何数字保持打开时,它会关闭后端特定的主循环。正因为如此,我想只需要进行少量调整,我们就可以完成完整的多后端 matplotlib。还不知道为什么要这样做,但我将可能性留在了 MainLoopBase 中。由于所有后端代码细节都被重构出来,FigureManager
这也有助于这一点,一位经理来统治它们(后端)。
Mdehoon:@OceanWolf,好的,谢谢你的解释。为后端提供统一的 API 对于 matplotlib 的可维护性非常重要。我认为这个 MEP 是朝着正确方向迈出的一步。