2012-04-22 17 views
6

DrawingAreaを使用して、PyGObjectGTK3を使用して単純なマップを描画する小さなアプリケーションがあります。GTK3とPyGObjectを使用してGdkPixbufを描画する方法

私は

from gi.repository import Gtk, GdkPixbuf 
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size("logo.png", 25, 25) 

を使用してPixbufをロードしDrawingAreaのドローイベント信号でそれを描画する

def draw(self, widget, context): 
    window = widget.get_window() 
    ctx = window.cairo_create() 
    ctx.set_source_pixbuf(pixbuf, 0, 0) 

を試みるが、私はエラーメッセージ

"AttributeError: 'cairo.Context' object has no attribute 'set_source_pixbuf'" 

を取得します私がGtk2 to Gtk3 migration guideを正しく読んでいるなら、これはうまくいくはずです。 私は何が間違っていますか?

+0

についてあなたが戻っget_windowから何かを引き出し可能に取得しているあなたは確かにあります? – stark

+0

はい、0xb71aab44(GdkX11Window at 0x9db5aa0)> 'オブジェクトバックで' gnirx

答えて

9

新しい描く信号がすでにパラメータとしてカイロコンテキストを渡すコールバックを使用しています公開イベントに出席しながら、あなたはカイロのコンテキストを取得するために私はPyGtkに行ったように、あなたはwindow = widget.get_window()のようなものを行う必要はありませんシグナル。 PYGObjectに簡単です:

import cairo 

class Foo(object): 
    def __init__(self): 

     (...) 
     self.image = cairo.ImageSurface.create_from_png('logo.png') 
     (...) 

    def draw(self, widget, context): 
     if self.image is not None: 
      context.set_source_surface(self.image, 0.0, 0.0) 
      context.paint() 
     else: 
      print('Invalid image') 
     return False 

あなたがPIXBUFを必要としませんが、何か他のもののためにそれを必要とする場合は、いくつかの選択肢がある場合であること:

  1. メモリ内の両方のオブジェクトを持つことを。両方がPNGからロードされている場合、メモリの浪費以外の問題はあまりないはずです。
  2. GdkPixbufをPIL Imageに変換し、次にPIL Imageをデータ配列に変換し、create_for_data()を使用してそのデータ配列からCairo ImageSurfaceを作成します。 Yak:Sよく分からない、Sorry:S
  3. gdk.cairo_set_source_pixbuf()が提案したホック。これは、ImageSurfaceでPixbufを描画する正しい方法だと思われますが、それはまったくうんざりです(そして、それは私がこのイントロスペクションのものを嫌う理由です、Cは悪いCポートのように見えます)。

あなたがここにひどい2番目のオプションを選択した場合はどのようにある:

import Image 
import array 
from gi.repository import Gtk, GdkPixbuf 

width = 25 
height = 25 
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size('logo.png', width, height) 
pil_image = Image.fromstring('RGBA', (width, height), pixbuf.get_pixels()) 
byte_array = array.array('B', pil_image.tostring()) 
cairo_surface = cairo.ImageSurface.create_for_data(byte_array, cairo.FORMAT_ARGB32, width, height, width * 4) 

注意create_for_data()not yet available for Python3only for Python2であること。

チェックこれはあなたが達成しようとしているものであればPyGObjectでダブルバッファを使用する方法についても私の答え:Drawing in PyGobject (python3)

種類は

+0

ありがとうございます。 ) – gnirx

+2

+1 "しかし、それはまったくうんざりです(これが私がこのイントロスペクションのものを嫌う理由は、すべてがCのように見えますが、悪いCポートのようなものです)。 " – xubuntix

6

次の仕事をするようだ:

def draw(self, widget, context): 
    Gdk.cairo_set_source_pixbuf(context, self.pixbuf, 0, 0) 
    context.paint() 

一つ疑問が残る:これは物事の好ましい方法ですか?

+1

私のプログラムは、 '' cairo_set_source_pixbuf''の助けを借りて "セグメンテーションフォールト"を生成しますか? –

+0

Gtkのドキュメントでは、「注意してください。この機能はカイロのものではありません...」と言います。私はこの上に答えを-1する必要がありますが、これを+1するのは建設的なようです。 Gtk3はカイロを使用してハンドラを表面に戻すので、外部ツールのように振る舞わないでください。描画がどこにあるのかが分かります。 – cox

+1

@AkashShende - '.cairo_get_source_pixbuf'を使用してセグメンテーションフォルトも取得していますが、これを修正する方法を見つけましたか? – nluigi

関連する問題