10

DrawingAreaとを使用して簡単なマップを描画するためにを使用する小さなアプリケーションがPyGObjectありGTK3ます。

Pixbufを使用してロードします

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

次に、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からGtk3への移行ガイドを正しく読んでいれば、これは機能するはずです。私は何が間違っているのですか?

4

2 に答える 2

10

新しいドローwindow = widget.get_window()シグナルは、cairo コンテキストをパラメーターとして既に渡しているコールバックを使用します。PyGtk で行ったように、エクスポーズ イベントシグナルに参加している間に cairo コンテキストを取得する必要はありません。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 イメージに変換し、次に PIL イメージをデータ配列に変換し、create_for_data() を使用してそのデータ配列から Cairo ImageSurface を作成します。Yak :SI よくわかりません、ごめんなさい :S
  3. hockによって提案されたGdk.cairo_set_source_pixbuf()を使用します。これは、ImageSurface で Pixbuf を描画する正しい方法のようですが、完全に Pythonic ではありません (そのため、私はこの Introspection のものを嫌います。すべてが 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()はPython3 ではまだ利用できず、 Python2しか利用できないことに注意してください。

これがあなたが達成しようとしているものである場合は、PyGObjectでダブルバッファを使用する方法に関する私の答えも確認してください: PyGobjectでの描画(python3)

敬具

于 2012-05-11T07:16:59.470 に答える
8

以下は仕事をしているようです:

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

まだ 1 つの疑問が残っています。これは好ましい方法ですか?

于 2012-04-23T19:48:50.133 に答える