0

キャンバス上にオブジェクトを動的に描画するために、wxPythonとCairoを使用して作成された新しいプロジェクトに取り組んでいます。すべてがうまく機能しますが、wxPythonには、回避するのに苦労しているという大きな警告があります。私はwxPythonにかなり慣れておらず、Cairoにも非常に慣れていないので、答えは明白かもしれませんが、どこにも見つからないようです。

私が遭遇している問題は、wx.EVT_PAINTが呼び出されたときにのみ、グラフィックスコンテキスト(wx.GraphicsContext、私は信じています)で描画できるようですが、キャンバスに描画できるように外部クラスが必要です。簡単に。

私の当初の計画は、Cairoコンテキストを作成し、それをキャンバスが存在するクラスに格納することでした。次に、描画するためにコンテキストにアクセスする必要があるクラスは、canvas.ctxなどを使用して簡単に取得できます。

私の全体的な質問は、wx.EVT_PAINTを呼び出さなくても、Cairoコンテキストにアクセスできる方法はありますか?

これが私が今使っているコードです:

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内から関数を呼び出さなくてもキャンバスに書き込むことができるようにすることです。

この質問を混乱させてしまったらごめんなさい。私は昨夜カイロを学び始めたばかりですが、それがどのように機能するのか、そしていくつかの正しい用語についてはまだ少し慣れていません。

ありがとうございました!

編集:私はいくつかのコードを忘れました:「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)
4

1 に答える 1

0

私は、Mike Driscoll の指示に従って (上記のコメントで)、 wxPython グループカイロ メーリング リストの両方に質問を投稿しました。カイロ リストのメンバーからの応答は次のとおりです。

wxWindowDC、wxClientDC を見てください。

これらのクラスを調べた後、次のように読みました。

アプリケーションが OnPaint イベントの外側からウィンドウのクライアント領域にペイントしたい場合は、wxClientDC を構築する必要があります。これは通常、一時的なスタック オブジェクトとして構築する必要があります。wxClientDC オブジェクトを保存しないでください。

これはまさに私が探していたものです。これが、将来同じ問題に遭遇した人に役立つことを願っています。

ありがとうございました!ジェレミー・オーバーマン

于 2012-07-25T21:55:15.320 に答える