2011-11-26 37 views
6

Kaydırılan bir pencerede bir dizi çizim alanı var (aslında cairo yüzeyleri, ama çok fazla önemli olduğunu sanmıyorum) ve çizimlerimi yenilemek istiyorum. Ancak, görüntüleri yeniden çizdiğimde, pencereyi yukarı ve aşağı kaydırıncaya kadar gösterilmezler. Bundan sonra rakamlar doğru, bu yüzden çizim rutininin kendisinin uygun olduğu sonucuna varmalıyım. Tüm bekleyen işlemleri beklemek üzere birgtk çizim alanını yenileme

while Gtk.events_pending(): 
     Gtk.main_iteration() 

döngüsünü de dahil ettim, ancak bu sorunu çözmüyor. Birisi bana başka ne eksik olduğunu işaret edebilir mi?

sayesinde

Tamam v923z, bu nedenle kodun daha büyük boyutta. Birincisi, boyamak için gidiyorum hangi üzerine bir çizim alanı tanımlayan bir sınıf (vücut düzgün girintili unutmayın Burada kodun büyük parçaları girinti nasıl bilmiyorum!):

class Preview: 
def __init__(self): 
    self.frame = Gtk.Frame() 
    self.frame.set_shadow_type(Gtk.ShadowType.IN) 
    self.frame.show() 
    self.da = Gtk.DrawingArea() 
    self.da.set_size_request(200, 300) 
    self.da.connect('configure-event', self.configure_event) 
    self.da.connect('draw', self.on_draw) 
    self.frame.add(self.da) 
    self.da.show() 

def configure_event(self, da, event): 
    allocation = da.get_allocation() 
    self.surface = da.get_window().create_similar_surface(cairo.CONTENT_COLOR, 
                  allocation.width, 
                  allocation.height) 
    cairo_ctx = cairo.Context(self.surface) 
    cairo_ctx.set_source_rgb(1, 1, 1) 
    cairo_ctx.paint() 
    return True 

def on_draw(self, da, cairo_ctx): 
    cairo_ctx.set_source_surface(self.surface, 0, 0) 
    cairo_ctx.paint() 
    return True 

pass 

Sonraki, aslında çizim alanını oluşturduğum nokta. viewport_preview, glade içinde oluşturulan bir görünümdür. Daha sonra önizlemeleri gösteren işlev. Bu sadece bir sonraki işlev için bir sarıcıdır ve buna ihtiyacım vardı çünkü ön izlemelerde bir girişi silersem, o vakayı ele almak zorundayım. İnanıyorum ki, bu işlevin sonundaki süre döngüsü gerekli değildir, çünkü bir sonrakinin sonunda olacak.

def draw_preview(self, counter=None): 
    if counter is not None: 
     self.vbox_preview.remove(self.previews[counter].frame) 
     self.previews.pop(counter) 
     self.pages.pop(counter) 
     self.vbox_preview.show() 
     while Gtk.events_pending(): 
      Gtk.main_iteration() 

    for i in range(len(self.pages)):  
     self.draw_note(self.previews[i].da, self.previews[i].surface, self.pages[i])    

    while Gtk.events_pending(): 
     Gtk.main_iteration() 

Son olarak, çizim işlevi kendisi:

def draw_note(self, widget, surface, page): 
    list_pos = '%d/%d'%(self.page + 1, len(self.pages)) 
    self.widget('label_status').set_text(list_pos) 
    cairo_ctx = cairo.Context(surface) 
    cairo_ctx.set_source_rgb(page.background[0], page.background[1], page.background[2]) 
    cairo_ctx.paint() 

    width, height = widget.get_size_request() 
    xmin, xmax, ymin, ymax = fujitsu.page_size(page) 

    factor = min(height/(2.0 * self.margin + ymax - ymin), width/(2.0 * self.margin + xmax - xmin)) 
    factor *= 0.8 
    page.scale = factor 
    value = self.widget('adjustment_smooth').get_value() 
    #print value 

    for pen in page.pagecontent: 
     x = self.margin + pen.path[0][0] - xmin 
     y = self.margin + pen.path[0][1] - ymin 

     cairo_ctx.move_to(x * factor, y * factor) 
     if self.widget('checkbutton_smooth').get_active() == False: 
      [cairo_ctx.line_to((self.margin + x - xmin) * factor, 
         (self.margin + y - ymin) * factor) for x, y in pen.path] 
     else: 
      bezier_curve = bezier.expand_coords(pen.path, value) 
      x = self.margin + bezier_curve[0][0][0] - xmin 
      y = self.margin + bezier_curve[0][0][1] - ymin 
      cairo_ctx.move_to(x * factor, y * factor) 
      [cairo_ctx.curve_to((self.margin + control[1][0] - xmin) * factor, 
           (self.margin + control[1][1] - ymin) * factor, 
           (self.margin + control[2][0] - xmin) * factor, 
           (self.margin + control[2][1] - ymin) * factor, 
           (self.margin + control[3][0] - xmin) * factor, 
           (self.margin + control[3][1] - ymin) * factor) 
                for control in bezier_curve] 

     cairo_ctx.set_line_width(pen.thickness * self.zoom_factor) 
     cairo_ctx.set_source_rgba(pen.colour[0], pen.colour[1], pen.colour[2], pen.colour[3]) 
     cairo_ctx.stroke() 

    cairo_ctx.rectangle(0, height * 0.96, width, height) 
    cairo_ctx.set_source_rgba(page.banner_text[0][0], page.banner_text[0][1], page.banner_text[0][2], page.banner_text[0][3]) 
    cairo_ctx.fill() 
    cairo_ctx.move_to(width * 0.05, height * 0.99) 
    cairo_ctx.show_text(self.filename + ' ' + list_pos) 
    cairo_ctx.set_font_size(self.zoom_factor * 10.0) 
    xbearing, ybearing, twidth, theight, xadvance, yadvance = (cairo_ctx.text_extents(page.banner_text[3])) 
    cairo_ctx.move_to(width - 1.03 * twidth, height * 0.99) 
    cairo_ctx.show_text(page.banner_text[3]) 
    cairo_ctx.set_source_rgba(0, 0, 0.9, 0.90) 
    cairo_ctx.stroke() 
    rect = widget.get_allocation() 
    widget.get_window().invalidate_rect(rect, False) 
    while Gtk.events_pending(): 
     Gtk.main_iteration() 

Ben bu konuda düşünüyorum.

cevap

3

Kirlenmedin olarak widget'ı (veya dikdörtgen) işaretler gtk_widget_queue_draw_area veya gdk_window_invalidate_rect .bu kullanabilir ve ana döngü boşta kez yeniden çizmek nerede expose olay alınacak. Sizden açıklamada, bu API'lerin kullanımda olabilmesi için güncellemelerin expose etkinliğinde gerçekleştiği görülüyor. Ayrıca gtk_widget_queue_draw_area kullanımını görebilirsiniz cairo sitesinden this sample kontrol edebilirsiniz.
Ben pygtk kullanmadıysanız ama Google'dan ben gtk_widget_queue_draw_area için ilgili çağrı gdk_window_invalidate_rect için gtk.Widget.queue_draw_area & bu yardımcı olur gtk.gdk.Window.invalidate_rect
Hope olduğunu bulduk!

+0

Cevabınız için teşekkürler! Ne yazık ki, bu sorunu çözmek için görünmüyor. Aslında, ben tüm boyunca gtk.gdk.Window.invalidate_rect olmuştu ve bunu bıraktığım zaman tuvalin hiç güncellenmediği doğru. Oldukça tuhaf bulduğum şey, çizim rutinimin tuvali beyaza boyaması ve üzerine çizgiler çizmesi ve resmin her zaman yapılmasıdır, ancak satırlar sadece kaydırılmış pencereleri yuvarlarsam gösterilir. Dolayısıyla, widget'ın en az bir kez güncellendiği anlaşılıyor. – v923z

+0

@ v923z: Ah tamam! Gerçekten kayıp olayları bir olay gibi görünüyordu! Yine de garip sesler duyuyorsun ... tuvali ortaya çıkarıyorsun olayları açığa vurduğumda geri çağırıyorum & tuvalin güncellenmesi beklenir bir kaç eksik çizgi çizimleri için beklemek, öyle mi? Mümkünse, belki bir kaç kod kodu gönderebilirsiniz ... –

+0

yardım etmeye çalışabiliriz Geri bildiriminiz için teşekkürler! Orijinal gönderimi güncelledim. – v923z