2012-04-22 9 views
6

Ho una piccola applicazione che usa un DrawingArea per disegnare una mappa semplice usando PyGObject e GTK3.Come disegnare un GdkPixbuf usando GTK3 e PyGObject

carico un Pixbuf utilizzando

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

e quindi provare a disegnarlo in DrawingArea 's disegnare segnale evento

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

ma ottengo il messaggio di errore

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

Se sto leggendo il Gtk2 to Gtk3 migration guide correttamente, questo dovrebbe funzionare. Cosa sto sbagliando?

+0

Sei sicuro che stai ricevendo qualcosa drawable ritorno da get_window ? – stark

+0

Sì, viene visualizzato un oggetto '' oggetto, quindi viene realizzato il widget DrawingArea. Mi sembra di essere in perdita di come si suppone che il disegno di pixbuf in Gtk3 funzioni. – gnirx

risposta

9

Il nuovo disegnare segnale utilizza un callback che passa già il contesto cairo come parametro, non c'è bisogno di fare cose del genere window = widget.get_window() come avete fatto in PyGTK per ottenere il contesto del Cairo per partecipare al esporre-evento segnale. In PYGObject è più semplice:

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 

che è se non è necessario il pixbuf, ma se ne avete bisogno per qualcos'altro sono disponibili diverse opzioni:

  1. di avere entrambi gli oggetti in memoria. Se entrambi vengono caricati da un PNG, non dovrebbero esserci molti problemi oltre allo spreco di memoria.
  2. Converti GdkPixbuf in PIL Image, quindi PIL Image nell'array di dati e quindi crea un ImageSurface Cairo da quell'array di dati utilizzando create_for_data(). Yak: S Non so meglio, mi dispiace: S
  3. Utilizzare Gdk.cairo_set_source_pixbuf() proposto da hock. Questo sembra essere il modo corretto di disegnare un Pixbuf in un ImageSurface, ma è totalmente antipolitico (ed è per questo che odio questo materiale di Introspezione, tutto sembra C, come una cattiva porta C).

Se si sceglie la seconda opzione terribile ecco come:

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) 

noti che create_for_data() è not yet available for Python3, only for Python2.

controllare anche la mia risposta su come utilizzare un doppio buffer in PyGObject se questo è quello che stai cercando di raggiungere: Drawing in PyGobject (python3)

Cordiali saluti

+0

Grazie. Questo sembra essere un modo molto più sicuro di gestire la grafica in GTK3 rispetto ai miei vari sforzi;) – gnirx

+2

+1 "ma è totalmente non -pitonico (ed è per questo che odio questo materiale di Introspezione, tutto sembra C, come una cattiva porta C). " – xubuntix

6

Quanto segue sembra fare il lavoro:

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

Una domanda rimane: è questo il modo migliore di fare le cose?

+1

il mio programma genera "errori di segmentazione" dopo l'esecuzione di '' cairo_set_source_pixbuf'' aiuto? –

+0

In Gtk doc dicono "stai attento, questa funzione non è da cairo ...". Dovrei -1 la risposta sopra questa, ma sembra più costruttivo fare +1 su questa. Gtk3 è un modo diverso di fare le cose, usa cairo e restituisce il gestore alla superficie, quindi non comportarti come se fosse uno strumento esterno: ci sono i luoghi in cui i disegni si succedono. – cox

+1

@AkashShende - Ricevo anche un errore di segmentazione usando '.cairo_get_source_pixbuf', hai capito come risolvere il problema? – nluigi

Problemi correlati