title: refresh drawing area in gtk
body: <p>I have a bunch of drawing areas (they are actually cairo surfaces, but I don't think it matters too much) in a scrolled window, and I would like to refresh the drawings. However, when I redraw the images, they are not shown till I scroll the window up and down. After that the figures are correct, so I have to conclude that the drawing routine itself is proper. I have also included a </p>
  
  <pre><code>    while Gtk.events_pending():
         Gtk.main_iteration()
  </code></pre>
  
  <p>loop to wait for all pending operations, but that does not solve the problem. Could someone point out to me what else is missing?</p>
  
  <p>Thanks,</p>
  
  <p>v923z</p>
  
  <p>OK, so the larger chunks of the code. First, a class defining the a drawing area onto which I am going to paint (note that the body is not indented properly! I don't know how to indent larger pieces of code here):</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Next, the point where I actually create the drawing area. viewport_preview is a viewport created in glade. </p>
  
  <pre><code>    self.previews = []
      self.widget('viewport_preview').remove(self.vbox_preview)
      self.vbox_preview = Gtk.VBox(homogeneous=False, spacing=8)
      self.widget('viewport_preview').add(self.vbox_preview)
      self.vbox_preview.show()
  
      for page in self.pages:
          preview = Preview()
          self.vbox_preview.pack_start(preview.frame, False, False, 10)
          self.previews.append(preview)
          while Gtk.events_pending():
              Gtk.main_iteration()
  
      self.draw_preview(None)
  
      return True
  </code></pre>
  
  <p>Then the function drawing the previews. This is really just a wrapper for the next function, and I needed this only because if I delete one entry in the previews, then I have to handle that case. I believe, the while loop at the end of this function is not necessary, for it will be at the end of the next one anyway.</p>
  
  <pre><code>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()
  </code></pre>
  
  <p>Finally, the drawing function itself:</p>
  
  <pre><code>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()
  </code></pre>
  
  <p>I think that's about it. </p>