Pan and zoom pcbnew view (canvas) to given X/Y position on the board


Is it possible to pan (and zoom) to a given X/Y location on the board using the pcbnew Python API?

Background: I have created a simple ActionPlugin that checks for return vias, i.e. some kind of custom EMI DRC. Vias without return vias in their vicinity are presented as a list in a dialog window (similar to regular DRC issues). I would like to pan and zoom the pcbnew window’s canvas to the location of the listed via if the corresponding list item is clicked.
Locating the via manually using its listed X/Y position is tedious.

Any help would be greatly appreciated!

Thank you in advance,

There is FocusOnLocation() from EDA_DRAW_FRAME and FocusOnItem(), but no idea if this is exposed to Python and if how you can get the frame in the Python API.

Edit: It doesn’t seem they are accessible via python API (See KiCad Pcbnew Python Scripting: Source File). Maybe there is a other way but i don’t know how.

Thanks for your research.

Do you (or somebody else) know whether there are technical obstacles that prevent the developers from exposing these methods and the frame (I would need the frame ID to let wx look it up, right?) to the Python API?

I guess that pan and zoom could be quite useful features for some Action Plugins.

Again, thanks for your help.

I suggest you create a feature request on gitlab. There are people that know more than i do.

Do you (or somebody else) know whether there are technical obstacles that prevent the developers from exposing these methods and the frame (I would need the frame ID to let wx look it up, right?) to the Python API?

I don’t know. Maybe you could try it on your system? AFAIK common/swig/kicad.i contains the list of exposed headers. Change it, recompile it, test it.

That might already be possible through wxWidget’s own API. You can import wx and call for example “wx.GetTopLevelWindows()”. Try to find out if you can navigate to the relevant object and call its methods, possibly starting from wx.Frame — wxPython Phoenix 4.2.1 documentation.

I’m interested in such functionality myself, so far I was able to get the canvas window:

def GetCanvas(self) -> wx.Window | None:
    window = wx.FindWindowByName("PcbFrame")
    found = []
    def _find(window):
        for child in window.GetChildren():
            if child.GetClassInfo().GetClassName() == "wxGLCanvas":
    _find(window)"Found: {found}")
    if found:
        return found[0]
    return None

I’m using ClassInfo because not all windows have names and ID is unknown.
The returned window is correct because I can:

if canvas := GetCanvas():
    canvas.Move(20, 20)

which updates my pcbnew window:

I didn’t figure out yet how to move window contents and not window itself.
I’m a little bit stuck currently. I’m looking ad wx.Window — wxPython Phoenix 4.2.1 documentation API, tried couple of functions, for example Scroll but without success.
I’m under impression that I need to get underlying canvas object and wx.Window is not what I need.

Without patching kicad code to expose internal canvas object and methods you will not be able to manipulate it from python directly.

You can try sending emulated mouse/keyboard events to the window, it will give you some control over the canvas.

I also saw ExecuteRemoteCommand function in pcb_edit_frame.h:

     * Execute a remote command send by Eeschema via a socket, port KICAD_PCB_PORT_SERVICE_NUMBER
     * (currently 4242).
     * This is a virtual function called by EDA_DRAW_FRAME::OnSockRequest().
     * @param cmdline is the received command from socket.
    void ExecuteRemoteCommand( const char* cmdline ) override;

when item is clicked on schematic it gets focused on pcb window, do you think it would be possible to emulate such remote command from python plugin?

No, those messages are passed through internal message system.

I managed to send some commands when pcbnew launched standalone, for example this works:

echo "\$NET: COL2" | nc 4242 

but indeed, $SELECT (which I determined eeschema is using when selecting element) does not work that way. Both eeschema and pcbnew need to be launched from main launcher but then neither is listening for external commands.

As far as I know, both the schematic editor and PCB editors have become a single program. I once read something about combining the executables to make communication between them easier.

But this also does not compute. When I look at their sizes, they are both about 7.5MB.

paul@cezanne:~$ ls -l /usr/bin/eeschema
-rwxr-xr-x 1 root root 7773688 Aug 14 01:14 /usr/bin/eeschema
paul@cezanne:~$ ls -l /usr/bin/pcbnew
-rwxr-xr-x 1 root root 7769592 Aug 14 01:14 /usr/bin/pcbnew

So now I don’t know if there is some truth in it, or if I’m writing gibberish at the moment.

Most of the application code is in shared libraries. Kicad main app loads them when you launch editors from project manager. So in a sense it’s a combined executable. But there are still separate binaries for eeschema/pcbnew for standalone mode.

FocusOnItem() is exposed in 7.99:

def FocusOnItem(aItem, aLayer=UNDEFINED_LAYER):
    r"""FocusOnItem(BOARD_ITEM aItem, PCB_LAYER_ID aLayer=UNDEFINED_LAYER)"""
    return _pcbnew.FocusOnItem(aItem, aLayer)

Thanks for the hint. This is great news!

Commit: add python api FocusOnItem (9d4e0ba4) · Commits · KiCad / KiCad Source Code / kicad · GitLab

I just gave it a try and it works wonderfully with my return via checker plugin. It keeps the zoom level (which the user can dynamically change while the non-modal plugin window stays open) and only pans to the selected item (via in my case). This is exactly what I was looking for.