PencilKit Framework for PyObjC
pyobjc-framework-pencilkit provides Python wrappers for Apple's PencilKit framework on macOS. It is part of the PyObjC project, a bidirectional bridge enabling Python scripts to interact with Objective-C libraries, including macOS Cocoa frameworks. The current version is 12.1 and it maintains an active release cadence, typically aligning with macOS SDK updates and Python version support.
Warnings
- breaking PyObjC frequently drops support for older Python versions. PyObjC 12.0 dropped support for Python 3.9, and PyObjC 11.0 dropped Python 3.8. Ensure your Python version is compatible with the PyObjC version you are installing.
- breaking PyObjC 11.1 changed how initializer methods (`init` family) are modeled, now correctly reflecting that they 'steal' a reference to `self` and return a new one, as per clang's ARC documentation. This affects object lifecycle and reference counting.
- gotcha PyObjC is a macOS-specific library and will not install or run on other operating systems. The frameworks it wraps (like PencilKit) are Apple-proprietary.
- gotcha Unlike Objective-C, where sending a message to `nil` (equivalent to Python `None`) is a no-op, attempting to call a method on a Python `None` object (which PyObjC translates from `nil`) will raise an `AttributeError`.
- gotcha Key-Value Observing (KVO) is not supported for pure Python objects. If you need KVO compatibility for properties of Python objects, they must inherit from `NSObject`. For observable sequence or dictionary instance variables, use `NSMutableArray` or `NSMutableDictionary` instead of Python lists or dictionaries.
Install
-
pip install pyobjc-framework-pencilkit
Imports
- PKCanvasView
from PencilKit import PKCanvasView
- PKToolPicker
from PencilKit import PKToolPicker
Quickstart
import AppKit
import Foundation
import PencilKit
from PyObjCTools import AppHelper
class PyPencilKitDelegate(AppKit.NSObject):
def applicationDidFinishLaunching_(self, notification):
# Create a window
self.window = AppKit.NSWindow.alloc().initWithContentRect_styleMask_backing_defer_(
Foundation.NSRect((100, 100), (600, 400)),
AppKit.NSWindowStyleMaskTitled | AppKit.NSWindowStyleMaskClosable | AppKit.NSWindowStyleMaskResizable,
AppKit.NSBackingStoreBuffered,
False
)
self.window.setTitle_("PyObjC PencilKit Demo")
self.window.setDelegate_(self)
# Create a PKCanvasView
self.canvasView = PencilKit.PKCanvasView.alloc().initWithFrame_(self.window.contentView().bounds())
self.canvasView.setAutoresizingMask_(AppKit.NSViewWidthSizable | AppKit.NSViewHeightSizable)
self.canvasView.setDrawingPolicy_(PencilKit.PKCanvasViewDrawingPolicyAnyInput) # Allow finger drawing
# Create and configure a PKToolPicker
self.toolPicker = PencilKit.PKToolPicker.alloc().init()
self.toolPicker.setVisible_forFirstResponder_(True, self.canvasView) # Make visible for the canvas
self.toolPicker.addObserver_(self.canvasView) # Canvas observes tool changes
self.window.contentView().addSubview_(self.canvasView)
self.window.makeKeyAndOrderFront_(None)
# Make canvas first responder to receive drawing input
self.window.makeFirstResponder_(self.canvasView)
def applicationShouldTerminateAfterLastWindowClosed_(self, sender):
return True
if __name__ == "__main__":
app = AppKit.NSApplication.sharedApplication()
delegate = PyPencilKitDelegate.alloc().init()
app.setDelegate_(delegate)
AppHelper.runEventLoop()