用 VSCode 编写自己的 KiCad 插件(下)

描述

 很多小伙伴都想自己开发 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 UiMainFrame
class 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 控件中的选择来显示特定图层。

  • GetSelectedRow() 方法返回当前选中的行索引。
  • GetValue(row, column) 方法获取指定行和列的值。
  • SetVisibleLayers(gal_set)设置可见图层集合。
  • 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:                continue            gal_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 App 
class StandAloneApp(App):    # StandAloneApp 类继承自 wx.App。用于管理应用程序的生命周期。    def __init__( self ):        super().__init__()
if __name__ == "__main__":    app = StandAloneApp()    from main_frame_view import MainFrameView    MainFrameView(None).Show()    app.MainLoop()

 

 

 

6、通过VSCode调试KiCad插件,在__main__.py页面下,点击Python Debugger:Debuge Python File”,出现GUI图形界面则表示运行成功。到这里 KiCad插件调试成功。

KiCAD

7、定义 KiCad 插件。

action_plugin.py 定义一个名为 Plugin 的类,继承自  pcbnew.ActionPlugin。ActionPlugin 是 KiCad 提供的基类,用于创建插件。当用户通过菜单或工具栏按钮触发插件时,Run() 方法被调用,显示插件的主界面。

  • self.name 设置插件的名称,显示在 KiCad 的菜单或工具栏中。
  • self.category 设置插件的类别,用于在 KiCad 的菜单中组织插件。
  • 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  # 可选,默认为 False        self.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 MainFrameView        MainFrameView(None).Show()

8、在kicad中加载和注册插件。

__init__.py 文件,通过动态修改 sys.path 来确保插件模块可以被正确导入,并调用插件的注册方法。
  • PLUGIN_ROOT 设置为当前脚本文件所在的目录路径。
  • Plugin().register() 创建 Plugin 类的一个实例,并调用该实例的 register() 方法注册插件
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
import sysimport os
PLUGIN_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插件是一个需要深入了解 KiCad API 的过程,而且代码的具体实现细节可能会比较复杂。如果你在开发过程中遇到具体的问题,可以查阅 KiCad的 官方文档或在相关的开发者社区寻求帮助。此外,确保你的代码能够适应 KiCad 版本的更新,以保持插件的长期可用性。

另外,从 KiCad 9 开始,将逐渐使用 IPC API 逐渐取代原来的 SWIG 方式。详情可以参考:KiCad 9 引入新的API机制


打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分