2012-07-24 4 views
0

Je travaille sur un nouveau projet écrit en utilisant wxPython et Cairo afin de dessiner dynamiquement des objets sur un canevas. Tout fonctionne plutôt bien, bien que je remarque un gros problème avec wxPython que j'ai du mal à contourner. Je suis assez nouveau sur wxPython, et très nouveau au Caire, donc la réponse peut être évidente, mais je n'arrive pas à la trouver nulle part. Le problème que je rencontre est qu'il semble que vous ne pouvez dessiner sur le contexte graphique (wx.GraphicsContext, je crois) quand wx.EVT_PAINT est appelé, mais j'ai besoin de classes externes pour pouvoir dessiner sur la toile facilement. Mon plan original était de créer le contexte de Le Caire puis de le stocker dans la classe sur laquelle se trouve le canevas, puis toute classe qui a besoin d'accéder au contexte pour le dessiner aurait besoin de quelque chose comme canvas.ctx.Dessin dynamique avec Cairo et wxPython

Ma question générale est la suivante: y a-t-il un moyen pour que je puisse avoir accès au contexte du Caire sans avoir besoin de wx.EVT_PAINT en train d'appeler?

Voici le code que je travaille avec en ce moment:

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() 

Dans ce code, ce que je veux accomplir est de faire canvas.DrawRectangle et ont la possibilité d'écrire sur la toile sans l'être fonction appelé depuis canvas.OnPaint. Désolé, si j'ai fait de cette question confuse. Je viens juste d'apprendre le Caire hier soir et je ne suis toujours pas familier avec le fonctionnement et la terminologie correcte pour certaines choses.

Merci!

EDIT: J'ai oublié un peu de code: Le module "CairoAPI" est quelque chose que j'ai obtenu à partir d'un tutoriel (je ne me souviens plus lequel est en main). Voici la source pour cela.

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) 
+0

Je reviendrais également au groupe d'utilisateurs wxPython. Les principaux devs fréquentent ce groupe et devraient pouvoir vous donner quelques indications. –

+0

Merci pour la réponse! Je vais certainement faire ça. – Jeremy

Répondre

0

Je fis comme Mike Driscoll m'a dirigé à faire (in the comment above) et affiché ma question à la fois sur le groupe wxPython et la liste de diffusion du Caire , et la réponse d'un membre de la liste du Caire était:

Jetez un coup d'œil à wxWindowDC, wxClientDC.

Après avoir recherché ces classes, je lis:

Un wxClientDC doit être construit si une application souhaite peindre sur la zone client d'une fenêtre à l'extérieur d'un événement OnPaint. Cela devrait normalement être construit comme un objet pile temporaire; ne stockez pas un objet wxClientDC.

C'est exactement ce que je cherchais. J'espère que cela aidera quelqu'un à rencontrer le même problème à l'avenir.

Merci! Jeremy Overman

+0

Vous pouvez également utiliser wx.MemoryDC pour rendre un wx.Bitmap à tout moment.Vous pouvez ensuite masquer le bitmap à l'écran pendant EVT_PAINT. – FogleBird