用 VSCode 编写自己的 KiCad 插件(下) “ 很多小伙伴都想自己开发 KiCad 插件,但不知从何入手。本文由华秋电子的另一位 KiCad 开发者波波同学撰写,分享了如何快速搭建环境,并开发一个简单的插件。 ”

所有环境配置成功,接下来可以写我们的python插件了。按照 kicad 官方开发手册,实现一个显示PCB对应图层的插件:
https://dev-docs.kicad.org/zh-cn/apis-and-binding/pcbnew/index.html
插件文件夹结构如下:
kicad_plugin/ # 插件目录 (Python 包)
- __init__.py # 此文件在导入软件包时执行 (在 Pcbnew 启动时)
- __main__.py # 调试python代码时使用
- action_plugin.py # ActionPlugin 派生类位于此处
- icon.png # 插件图标
- main_frame_view.py # 其他 Python 代码
- ui_main_frame.fbp # wxformbuilder生成的源代码
- ui_main_frame.py # wxformbuilder生成的python代码
[插件示例仓库]:
https://github.com/Huaqiu-Electronics/my-kicad-plugin.git
代码实现
1、插件页面布局。
上文通过 wxformbuilder 生成了 ui_main_frame.py 的 UiMainFrame 类。新建 main_frame_view.py 文件,定义一个名为 MainFrameView 的类,它继承自 UiMainFrame,MainFrameView 继承了 UiMainFrame 的所有属性和方法。初始化一个带有两列的 self.data_view_list 控件,并设置列的样式。
AppendTextColumn() 方法用于向 DataView 中添加一个文本列。
from ui_main_frame import UiMainFrameclass MainFrameView(UiMainFrame):def __init__(self, parent):super().__init__(parent)self.data_view_list.AppendTextColumn("ID",0,width=50,align=wx.ALIGN_CENTER,flags=dv.DATAVIEW_COL_RESIZABLE,)self.data_view_list.AppendTextColumn("Layer",1,width=170,align=wx.ALIGN_CENTER,flags=dv.DATAVIEW_COL_RESIZABLE,)
2、加载PCB对象。
首先尝试获取当前 PCB 文件的文件名。pcbnew.GetBoard() 返回当前加载的 PCB 对象,并将 PCB 对象赋值给 self.board 。如果加载失败,则尝试加载一个指定路径的文件,使用 pcbnew.LoadBoard() 方法加载该pcb文件,并将返回的 PCB 对象赋值给 self.board。
try:#通过 kicad 打开插件时调用pcbnew.GetBoard().GetFileName()self.board = pcbnew.GetBoard()except Exception as e:# VSCode 调试插件时调用fp = "C:\Program Files\demos\flat_hierarchy\flat_hierarchy.kicad_pcb" # Replace with your own PCB file path.if os.path.exists(fp):self.board = pcbnew.LoadBoard(fp)else:print("File not find")
3、从 KiCad 的 PCB 文件中获取可见图层的信息,并将这些信息添加到一个 DataView 控件中。
GetVisibleLayers() 方法返回一个包含所有可见图层的集合。
GAL_LayerSet 是用于管理 KiCad 图层的类。
gal_set.Seq() 返回一个包含所有可见图层编号的序列。
AppendItem(data) 方法将 data 列表中的内容作为一行添加到 DataView 控件中。
def fill_list_data(self):data = []gal_set = self.board.GetVisibleLayers()for num in [x for x in gal_set.Seq()]:layerName = self.board.GetLayerName(num)data = [ str( num ), layerName ]self.data_view_list.AppendItem(data)
4、显示特定图层的实现。
on_show_layer()方法是一个事件处理函数,用于在 KiCad 的 GUI 中显示或隐藏特定的图层。on_show_layer() 方法与一个事件项关联绑定,当用户触发该事件时,它会根据用户在 DataView 控件中的选择来显示特定图层。
UpdateUserInterface() 方法更新 KiCad 的用户界面,以反映图层的更改。
使用def on_show_layer(self, event):selection = self.data_view_list.GetSelectedRow()item_data = self.data_view_list.GetValue(selection, 0)self.board.SetVisibleAlls()gal_set = self.board.GetVisibleLayers()for num in [x for x in gal_set.Seq()]:if str(num) == item_data:continuegal_set.removeLayer(num)self.board.SetVisibleLayers(gal_set)pcbnew.UpdateUserInterface()wx.CallAfter(pcbnew.Refresh)event.Skip()pass
wx.dataview.DataViewCtrl 的 Bind 方法来绑定事件处理函数。通过单击事件调用 on_show_layer() 方法。
dv.EVT_DATAVIEW_SELECTION_CHANGED 是一个事件类型,表示用户通过单击激活数据项。
self.data_view_list.Bind(dv.EVT_DATAVIEW_SELECTION_CHANGED, self.on_show_layer)
5、启动一个基于 wxPython 的独立应用程序。
在 __main__.py 中启动插件。从 wx 模块中导入 App 类,定义一个名为 StandAloneApp 的类继承自 App。StandAloneApp 用于管理应用程序的生命周期,并在主程序中实例化该类,显示主窗口。
Show() 方法显示主窗口。
app.MainLoop() 方法启动应用程序的主事件循环。MainLoop 负责处理用户交互、窗口更新等事件。
from wx import Appclass StandAloneApp(App):# StandAloneApp 类继承自 wx.App。用于管理应用程序的生命周期。def __init__( self ):super().__init__()if __name__ == "__main__":app = StandAloneApp()from main_frame_view import MainFrameViewMainFrameView(None).Show()app.MainLoop()
6、通过VSCode调试KiCad插件,在__main__.py页面下,点击“Python Debugger:Debuge Python File”,出现GUI图形界面则表示运行成功。到这里 KiCad插件调试成功。

7、定义 KiCad 插件。
action_plugin.py 定义一个名为 Plugin 的类,继承自 pcbnew.ActionPlugin。ActionPlugin 是 KiCad 提供的基类,用于创建插件。当用户通过菜单或工具栏按钮触发插件时,Run() 方法被调用,显示插件的主界面。
self.description 插件的功能描述,显示在 KiCad 的插件管理器中。
self.icon_file_name 设置插件的图标文件路径。
self.dark_icon_file_name 设置插件的深色模式图标文件路径。
import pcbnewimport osimport wx# 插件入口class Plugin(pcbnew.ActionPlugin):def __init__(self):self.name = "MyPlugin" # 插件名称self.category = "Manufacturing" # 描述性类别名称self.description = "To show or to hide layer." # 对插件及其功能的描述self.show_toolbar_button = True # 可选,默认为 Falseself.icon_file_name = os.path.join(os.path.dirname(__file__), "icon.png") # 可选,默认为 ""self.dark_icon_file_name = os.path.join(os.path.dirname(__file__), "icon.png")def Run(self):from main_frame_view import MainFrameViewMainFrameView(None).Show()
8、在kicad中加载和注册插件。
__init__.py 文件,通过动态修改sys.path 来确保插件模块可以被正确导入,并调用插件的注册方法。import sysimport osPLUGIN_ROOT = os.path.dirname(os.path.abspath(__file__))if PLUGIN_ROOT not in sys.path:sys.path.append(PLUGIN_ROOT)from action_plugin import PluginPlugin().register()
9、插件代码完成之后就可以使用自己编写的插件了。在PCB中打开“工具-->外部插件-->打开插件目录”,进入到插件目录,将插件页面放在kicad 插件目录下面:”C:UsershafDocumentsKiCad9.0scriptingplugins ”或同级目录下的” C:UsershafDocumentsKiCad9.03rdpartyplugins ”。插件如下图,通过点击就可以显示对应的PCB图层了。

结束语
编写KiCad插件是一个需要深入了解 KiCad API 的过程,而且代码的具体实现细节可能会比较复杂。如果你在开发过程中遇到具体的问题,可以查阅 KiCad的 官方文档或在相关的开发者社区寻求帮助。此外,确保你的代码能够适应 KiCad 版本的更新,以保持插件的长期可用性。
另外,从 KiCad 9 开始,将逐渐使用 IPC API 逐渐取代原来的 SWIG 方式。详情可以参考:KiCad 9 引入新的API机制。
全部0条评论
快来发表一下你的评论吧 !