2010-08-18 22 views
3

Je commence juste à utiliser pycairo, et je suis tombé sur l'erreur intéressante suivante. Le programme que j'écris crée une fenêtre gtk simple, dessine un rectangle dessus, et a ensuite un rappel pour dessiner une ligne aléatoire sur n'importe quel type d'entrée au clavier. Cependant, il semble que pour chaque saisie au clavier, je doive créer un nouveau contexte, sinon j'obtiens une erreur au moment où le programme reçoit la première entrée au clavier (en particulier, sur la ligne .stroke()). L'erreur est la suivante, si c'est important. 'BadDrawable (paramètre Pixmap ou fenêtre invalide)'. (Détails: serial 230 code_erreur 9 code_recherche 53 code_minimal 0)Le contexte et la persistance du Caire?

#! /usr/bin/env python 
import pygtk 
pygtk.require('2.0') 
import gtk, gobject, cairo, math, random 
# Create a GTK+ widget on which we will draw using Cairo 
class Screen(gtk.DrawingArea): 
# Draw in response to an expose-event 
    __gsignals__ = { "expose-event": "override" } 

    # Handle the expose-event by drawing 
    def do_expose_event(self, event): 
    # Create the cairo context 
    self.cr = self.window.cairo_create() 
    # Restrict Cairo to the exposed area; avoid extra work 
    self.cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) 
    self.cr.clip() 

    self.draw(*self.window.get_size()) 

    def key_press_event(self, *args): 
    # print args 
    self.cr = self.window.cairo_create() # This is the line I have to add 
    # in order to make this function not throw the error. Note that cr is only 
    # given as attribute of self in order to stop it going out of scope when this line 
    # doesn't exist 
    self.cr.set_source_rgb(random.random(), random.random(), random.random()) 
    self.cr.move_to(*[z/2.0 for z in self.window.get_size()]) 
    self.cr.line_to(*[z*random.random() for z in self.window.get_size()]) 
    self.cr.stroke() 

    def draw(self, width, height): 
    # Fill the background with gray 
    self.cr.set_source_rgb(.5,.5,.5) 
    self.cr.rectangle(0, 0, width,height) 
    self.cr.fill() 

    self.cr.set_source_rgb(1,0,0) 
    self.cr.arc(width/2.0, height/2.0, min(width,height)/2.0 - 20.0, 0.0, 2.0*math.pi) 
    self.cr.stroke() 

#create a gtk window, attach to exit button, and whatever is passed as arg becomes the body of the window. AWESOME 
def run(Widget): 
    window = gtk.Window() 
    widget = Widget() 
    window.connect("delete-event", gtk.main_quit) 
    window.connect('key-press-event',widget.key_press_event) 
    widget.show() 
    window.add(widget) 
    window.present() 
    gtk.main() 

if __name__ == "__main__": 
    run(Screen) 

Merci pour votre aide!

(Mise à jour: Je jouais, et j'ai réalisé ce qui suit: quand je redimensionnez la fenêtre, tous les nouveaux objets qui ont été ajoutés sont supprimés (ou au moins ne semblent pas plus)?)

+1

Vous pourriez être intéressé par http://wiki.github.com/tbaugis/hamster_experiments/ - il fournit une abstraction très utile au sommet du Caire. Même si vous n'utilisez pas la bibliothèque complète, le tweener inclus vaut certainement la peine d'être consulté. –

Répondre

2

dessins Caire ne persiste pas du tout. (Il vaut mieux ne pas les considérer comme des "objets" - ce n'est pas comme une bibliothèque de canvas où vous pouvez les déplacer ou les transformer après les avoir dessinés.) Vous devez faire tout le dessin dans le gestionnaire d'exposition, ou sera, comme vous l'avez découvert, disparaître chaque fois que la fenêtre est redessinée.

Le contexte du cairo ne persiste pas à cause de la double mise en mémoire tampon: voir le note in the C documentation, que je n'ai malheureusement trouvé nulle part dans la documentation de PyGTK.

Dans le code ci-dessus, vous devez générer les coordonnées et la couleur de votre ligne aléatoire dans le gestionnaire de touches et les enregistrer dans un tableau. Ensuite, dans le gestionnaire d'exposition, dessinez chaque ligne dans le tableau dans l'ordre.

+0

Après avoir dormi sur le problème, j'ai réalisé que c'était probablement quelque chose de similaire à l'idée de la toile. Merci d'avoir comblé les lacunes sur le fonctionnement du Caire. Je suppose que je ne prenais pas assez au sérieux la métaphore de la toile. –

0

De nombreuses saveurs de la persistance à discuter:

Dessins sur certaines surfaces ne persistent pas: les surfaces de l'interface graphique. Vous devez les redessiner dans le rappel d'exposition.

objets pycairo ne doivent pas être traités comme des objets persistants, seulement comme une interface aux fonctions de la bibliothèque du Caire en C.

Le contenu (chemins et remplissages) des contextes du Caire ne persistent pas au-delà d'un accident vasculaire cérébral () ou remplir().

Un contexte pour une surface GUI ne persiste pas entre les événements d'exposition (à cause de la double mise en mémoire tampon?) (Je ne sais pas si un contexte persiste pour d'autres surfaces. pour stocker les attributs d'une fenêtre (une fenêtre sur un document, c'est-à-dire un modèle en coordonnées utilisateur.)

La persistance visuelle est la tendance de l'œil humain à voir la lumière après qu'elle a cessé. Les fantômes et le scintillement sont ses symptômes dans l'animation ou la vidéo. La désactivation de la double mise en mémoire tampon permet de voir les choses telles qu'elles sont dessinées, c'est-à-dire d'activer l'animation dans un événement d'exposition (simulation des symptômes de persistance visuelle). La désactivation du double tampon ne rend pas un contexte persistant entre les événements.

La persistance de la mémoire est la vraie persistance, ou devrais-je dire surréaliste.