使用Cairo和wxPython进行动态绘图

使用Cairo和wxPython进行动态绘图,python,dynamic,wxpython,cairo,Python,Dynamic,Wxpython,Cairo,我正在做一个新项目,它是使用wxPython和Cairo编写的,以便在画布上动态绘制对象。尽管我注意到wxPython的一个大警告,我在工作中遇到了困难,但一切都很顺利。我对wxPython很陌生,对开罗也很陌生,所以答案可能很明显,但我似乎在任何地方都找不到 我遇到的问题是,似乎只有在调用wx.EVT_PAINT时才能在图形上下文(我相信是wx.GraphicsContext)上进行绘制,尽管我需要外部类才能轻松地绘制到画布上 我最初的计划是创建Cairo上下文,然后将其存储在画布所在的类中,

我正在做一个新项目,它是使用wxPython和Cairo编写的,以便在画布上动态绘制对象。尽管我注意到wxPython的一个大警告,我在工作中遇到了困难,但一切都很顺利。我对wxPython很陌生,对开罗也很陌生,所以答案可能很明显,但我似乎在任何地方都找不到

我遇到的问题是,似乎只有在调用wx.EVT_PAINT时才能在图形上下文(我相信是wx.GraphicsContext)上进行绘制,尽管我需要外部类才能轻松地绘制到画布上

我最初的计划是创建Cairo上下文,然后将其存储在画布所在的类中,然后任何需要访问上下文才能绘制的类都可以使用canvas.ctx之类的东西简单地获得它

我的总体问题是,是否有任何方法可以在不需要调用wx.EVT_PAINT的情况下访问开罗上下文

以下是我目前正在使用的代码:

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()
在这段代码中,我想要完成的是使canvas.DrawRectangle成为一个画布,并且能够在不从canvas.OnPaint中调用函数的情况下写入画布

对不起,我把这些问题弄糊涂了。我昨晚刚开始学习Cairo,但我对它的工作原理和某些方面的正确术语仍然有点不熟悉

谢谢大家!

编辑:我忘了一些代码:“CairoAPI”模块是我从一个教程中得到的(我一时记不清是哪一个)。这是它的来源

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)

我按照Mike Driscoll的指示做了()并将我的问题发布在wxPython组和开罗邮件列表上,开罗列表中的一名成员的回复是:

看看wxWindowDC,wxClientDC

查找这些课程后,我读到:

如果应用程序希望从OnPaint事件外部在窗口的客户端区域上绘制,则必须构造wxClientDC。通常应将其构造为临时堆栈对象;不要存储wxClientDC对象

这正是我想要的。我希望这能帮助将来遇到同样问题的人

谢谢大家!!
杰里米·奥夫曼(Jeremy Overman)

我也会重新发布到wxPython用户组。主要开发人员经常访问该组,应该能够给您一些建议。感谢您的回复!我肯定会这样做。你也可以随时使用wx.MemoryDC渲染到wx.Bitmap。然后,您可以在EVT_绘制期间将位图快速显示到屏幕上。