2012-04-22 62 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 2012-04-22 20:50:41

+0

是的,我在0xb71aab44(GdkX11Window在0x9db5aa0)>對象處得到一個'gtk.gdk.X11Window對象,所以DrawingArea小部件就實現了。我似乎不知道在Gtk3中如何繪製pixbufs應該工作。 – gnirx 2012-04-22 21:02:51

回答

9

信號採用已經經過開羅上下文參數的回調,你不需要做這樣的東西window = widget.get_window()像你的PyGTK做得到開羅方面在出席暴露事件信號。在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。犛牛:S我不知道更好,對不起:S
  3. 使用Gdk.cairo_set_source_pixbuf()由hock提出。這似乎是在ImageSurface中繪製Pixbuf的正確方法,但它完全沒有問題(這就是爲什麼我討厭這種自省的東西,所有看起來像C,就像一個不好的C端口)。

如果您選擇在這裏可怕的第二個選項是如何:

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

謝謝。這似乎是GTK3中處理圖形的一種比我的各種努力更好的方式;) – gnirx 2012-05-12 21:26:35

+2

+ 1「,但它完全不混淆(這就是爲什麼我討厭這種自省的東西,所有看起來像C,就像一個壞的C端口)。 「 – xubuntix 2012-12-17 12:06:44

6

下,似乎做的工作:

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

一個問題仍然存在:這是做事的首選方式?

+1

我的程序在執行cairo_set_source_pixbuf後會產生「段錯誤」嗎? – 2013-09-15 06:41:54

+0

在Gtk文檔中,他們說「要小心,這個功能不是來自開羅......」。我應該回答這個問題,但似乎更有建設性的+1。 Gtk3是一種不同的方式,它使用cairo並將處理程序返回到表面,所以不要像它是一個外部工具那樣工作:圖形發生的地方。 – cox 2014-01-22 17:35:37

+1

@AshashShende - 我也使用'.cairo_get_source_pixbuf'得到一個分段錯誤,你弄清楚如何解決這個問題? – nluigi 2016-10-30 07:41:50

相關問題