Domanda

Io sono solo l'inizio utilizzando pycairo, e mi sono imbattuto nel seguente errore interessante. Il programma che ho scrittura crea una semplice finestra gtk, disegna un rettangolo su di esso, e quindi ha un callback per disegnare una linea a caso su qualsiasi tipo di input da tastiera. Tuttavia, sembra che ad ogni ingresso tastiera, devo creare un nuovo contesto, o un errore momentaneamente il programma riceve primo ingresso tastiera (specificamente, sulla linea .stroke ()). Errore è la seguente, se è importante. 'BadDrawable (non valida Pixmap o il parametro Window)'. (Dettagli: di serie 230 error_code 9 request_code 53 minor_code 0)

#! /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)

Grazie per il vostro aiuto!

(Update: stavo giocando in giro, e mi sono reso conto quanto segue:? Quando ho ridimensionare la finestra, tutti i nuovi oggetti che sono stati aggiunti vengono eliminati (o almeno non appaiono più))

È stato utile?

Soluzione

disegni

??Il Cairo non persistono a tutti. (E 'meglio non pensare a loro come "oggetti" -. Non è come una biblioteca di tela in cui è possibile spostare o trasformarli dopo averli disegnato) Devi fare tutti i disegni nel gestore esporre, oppure sarà, come avete scoperto, scompare ogni volta che la finestra viene ridisegnato.

Il contesto cairo non persistono a causa del doppio buffer: vedere la nota nella documentazione di C, che purtroppo non riuscivo a trovare da nessuna parte nella documentazione PyGTK.

Nel codice di cui sopra, si dovrebbe generare le coordinate e il colore della linea a caso nel gestore di pressione dei tasti e salvarle in un array. Poi nel gestore di esporre, disegnare ogni riga della matrice in ordine.

Altri suggerimenti

mentre si deve creare il contesto ogni corsa, è possibile ottenere la persistenza siete alla ricerca di disabilitando il doppio buffering del widget.

Ecco un esempio utilizzando libreria grafica criceto che proprio non che:

https://github.com/projecthamster/experiments/blob/master/ many_lines.py

Molti sapori di persistenza da discutere:

I disegni su alcuni superfici non persistono: superfici GUI. Si dovrebbe ridisegnare nel callback esporre.

oggetti PyCairo non deve essere trattato come oggetti persistenti, solo come interfaccia per le funzioni della libreria Cairo nel C.

I contenuti (percorsi e riempimenti) dei contesti Cairo non persistono oltre un ictus () o un riempimento () operazione.

Un contesto per una superficie GUI non persistono tra espone gli eventi (a causa del doppio buffering?) (Non so se un persiste contesto per altre superfici cioè dispositivi.) Quindi non è possibile utilizzare un contesto cairo a memorizzare gli attributi di una finestra (una finestra su un modello documento cioè in coordinate utente.)

visiva persistenza è la tendenza del l'occhio umano a vedere la luce dopo che è cessato. Fantasmi e flicker sono i suoi sintomi in animazione o video. Disabilitare il doppio buffer consente di vedere le cose come sono disegnati, che è, consentendo l'animazione all'interno di un evento di esposizione (la simulazione dei sintomi di persistenza visiva.) Disattivazione doppio buffer non fa un contesto su una superficie GUI permanente tra esporre eventi.

La persistenza della memoria è l'ur vero persistenza, o dovrei dire surreale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top