[cairo] Dynamic Drawing in Cairo and wxPython

Jeremy Overman jeremyoverman at overmanscomputers.com
Tue Jul 24 18:04:14 PDT 2012


Hi! I'm working on a new project that is written using wxPython and Cairo
in order to dynamically draw objects on a canvas. Everything works pretty
well, though I'm noticing a big caveat with wxPython that I'm having a hard
time working around. I'm am fairly new to wxPython, and very new to Cairo,
so the answer may be obvious, but I can't seem to find it anywhere.

The problem I'm running into is that it seems that you are only able to
draw on the graphics context (wx.GraphicsContext, I believe) when
wx.EVT_PAINT is called, though I need external classes to be able to draw
to the canvas easily.

My original plan was to create the Cairo context then store it in the class
that the canvas is on, then any class that needs access to the context to
draw would simple get it using something like canvas.ctx.

My overall question is, is there any way that I can have access to the
Cairo Context without needing wx.EVT_PAINT being calling?

Here's the code I'm working with right now:

import wx
import CairoAPI

class Canvas(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, -1, "test", pos=(0, 0), size=(640,480))

        #self.ShowFullScreen(1)
        self.Bind(wx.EVT_PAINT, self.OnPaint)

    def DrawRectangle(self):
        pass

    def OnPaint(self, event):

        dc = wx.PaintDC(self)

        w,h = dc.GetSizeTuple()

        gc = wx.GraphicsContext.Create(dc)

        nc = gc.GetNativeContext()
        ctx = CairoAPI.Context_FromSWIGObject(nc)


if __name__=="__main__":

    app = wx.App()

    canvas = Canvas()
    canvas.Show()

    app.MainLoop()

In this code, what I want to accomplish is to make canvas.DrawRectangle
have the ability to write to the canvas without the function being called
from within canvas.OnPaint.

Also, I used code from a tutorial I read, and made module out of it, thus
CairoAPI. The code for it is as follows:

import ctypes
import cairo
from ctypes.util import find_library

cairo_dll = ctypes.CDLL(find_library("cairo"))

# Pycairo's API representation (from pycairo.h)
class Pycairo_CAPI(ctypes.Structure):

   _fields_ = [
      ('Context_Type', ctypes.py_object),

      ('Context_FromContext', ctypes.PYFUNCTYPE(ctypes.py_object,

                                                ctypes.c_void_p,
                                                ctypes.py_object,

                                                ctypes.py_object)),
      ('FontFace_Type', ctypes.py_object),

      ('FontFace_FromFontFace', ctypes.PYFUNCTYPE(ctypes.py_object,
ctypes.c_void_p)),

      ('FontOptions_Type', ctypes.py_object),

      ('FontOptions_FromFontOptions',
ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)),

      ('Matrix_Type', ctypes.py_object),

      ('Matrix_FromMatrix', ctypes.PYFUNCTYPE(ctypes.py_object,
ctypes.c_void_p)),

      ('Path_Type', ctypes.py_object),

      ('Path_FromPath', ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)),

      ('Pattern_Type', ctypes.py_object),

      ('SolidPattern_Type', ctypes.py_object),

      ('SurfacePattern_Type', ctypes.py_object),

      ('Gradient_Type', ctypes.py_object),

      ('LinearGradient_Type', ctypes.py_object),

      ('RadialGradient_Type', ctypes.py_object),

      ('Pattern_FromPattern', ctypes.c_void_p),

      ('ScaledFont_Type', ctypes.py_object),

      ('ScaledFont_FromScaledFont',
ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)),

      ('Surface_Type', ctypes.py_object),

      ('ImageSurface_Type', ctypes.py_object),

      ('PDFSurface_Type', ctypes.py_object),

      ('PSSurface_Type', ctypes.py_object),

      ('SVGSurface_Type', ctypes.py_object),

      ('Win32Surface_Type', ctypes.py_object),

      ('XlibSurface_Type', ctypes.py_object),

      ('Surface_FromSurface', ctypes.PYFUNCTYPE(ctypes.py_object,
ctypes.c_void_p)),

      ('Check_Status', ctypes.PYFUNCTYPE(ctypes.c_int, ctypes.c_int))]

# look up the API
ctypes.pythonapi.PyCObject_Import.restype = ctypes.POINTER(Pycairo_CAPI)

pycairo_api = ctypes.pythonapi.PyCObject_Import("cairo", "CAPI").contents

ContextType = pycairo_api.Context_Type

def Context_FromSWIGObject(swigObj):
    ptr = ctypes.c_void_p(int(swigObj))

    #increment the native context's ref count, since the
Pycairo_Context decrements it
    #when it is finalised.

    cairo_dll.cairo_reference(ptr)
    return pycairo_api.Context_FromContext(ptr, ContextType, None)

Sorry if I've made this question confusing. I just started learning Cairo
last night and I'm still a little unfamiliar with how it works and the
correct terminology for some things.

Thank you!
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.cairographics.org/archives/cairo/attachments/20120724/20d05d62/attachment-0001.html>


More information about the cairo mailing list