2011-11-26 57 views
6

我有一堆畫圖區(他們實際上是開羅面,但我不認爲它很重要太多了)在滾動窗口,我想刷新圖紙。但是,當我重新繪製圖像時,直到我向上和向下滾動窗口時才顯示它們。之後,數字是正確的,所以我必須得出結論,繪圖程序本身是適當的。我還包括一個刷新繪圖區域在GTK

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

循環等待所有掛起的操作,但這並不能解決問題。有人能指出我還缺少了什麼嗎?

感謝,

v923z

OK,所以代碼的更大的塊。首先,確定在其上,我要畫的繪圖區域類(注意,身體不能正常縮進我不知道該怎麼縮進大塊的代碼在這裏!):

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 

接下來,我實際創建繪圖區的地步。 viewport_preview是在glade中創建的視口。

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 

然後繪製預覽的功能。這實際上只是下一個函數的一個包裝,我只需要這個,因爲如果我在預覽中刪除了一個條目,那麼我必須處理該情況。我相信,這個函數結束時的while循環是沒有必要的,因爲無論如何,它將在下一個循環的末尾。

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() 

最後,繪圖函數本身:

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() 

我想這就是它。

回答

3

您可以使用gtk_widget_queue_draw_areagdk_window_invalidate_rect。這將標記窗口小部件(或矩形)爲髒,並且一旦主循環空閒,將會收到在您可以重繪的地方的事件。從你的描述看來,更新發生在expose事件上,所以這些API可能是有用的。您也可以從開羅網站,在這裏你可以看到gtk_widget_queue_draw_area使用檢查this sample
我沒有使用過的PyGTK但是從谷歌我發現,相應的呼籲gtk_widget_queue_draw_areagtk.Widget.queue_draw_area &爲gdk_window_invalidate_rectgtk.gdk.Window.invalidate_rect
希望這有助於!

+0

感謝您的答覆!不幸的是,這似乎並沒有解決問題。事實上,我一直都有gtk.gdk.Window.invalidate_rect,並且確實如果我將其保留,那麼畫布根本不會更新。我覺得很奇怪的是,我的繪圖程序將畫布塗成白色,然後在其上繪製線條,並且繪畫始終完成,但只有在滾動滾動窗口時才顯示線條。所以,這個小部件至少會更新一次。 – v923z

+0

@ v923z:好的!它確實看起來像是一個缺少揭露事件的案例!聽起來很奇怪,雖然...你正在刷新公佈事件回調中的畫布我認爲和畫布正在更新期望一些缺失的線條畫,是嗎?如果可能的話,也許你可以發佈一些代碼......我們可以嘗試幫助 –

+0

感謝您的反饋!我已更新了我的原始帖子。 – v923z