2011-11-26 20 views
6

Tôi có một vùng vẽ (chúng thực sự là bề mặt cairo, nhưng tôi không nghĩ nó quan trọng quá nhiều) trong một cửa sổ cuộn, và tôi muốn làm mới các bản vẽ. Tuy nhiên, khi tôi vẽ lại hình ảnh, chúng không được hiển thị cho đến khi tôi cuộn cửa sổ lên và xuống. Sau đó các số liệu là chính xác, vì vậy tôi phải kết luận rằng bản vẽ thường trình là chính xác. Tôi cũng đã bao gồm một sốvùng vẽ làm mới trong gtk

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

lặp lại để chờ tất cả các thao tác đang chờ xử lý, nhưng điều đó không giải quyết được sự cố. Ai đó có thể chỉ ra cho tôi những gì khác là mất tích?

Cảm ơn,

v923z

OK, vì vậy các khối lớn của mã này. Thứ nhất, một lớp học để định dạng vùng vẽ lên đó tôi sẽ vẽ (lưu ý rằng cơ thể không được thụt vào đúng Tôi không biết làm thế nào để thụt mảnh lớn của mã ở đây!):

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 

Tiếp theo, điểm mà tôi thực sự tạo ra khu vực vẽ. viewport_preview là một khung nhìn được tạo trong 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 

Sau đó, chức năng sẽ vẽ bản xem trước. Điều này thực sự chỉ là một wrapper cho các chức năng tiếp theo, và tôi cần thiết này chỉ vì nếu tôi xóa một mục trong xem trước, sau đó tôi phải xử lý trường hợp đó. Tôi tin rằng, vòng lặp while ở phần cuối của hàm này là không cần thiết, vì nó sẽ ở cuối của phần tiếp theo.

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

Cuối cùng, chức năng vẽ bản thân:

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

Tôi nghĩ đó là về nó.

Trả lời

3

Bạn có thể sử dụng gtk_widget_queue_draw_area hoặc gdk_window_invalidate_rect. Điều này sẽ đánh dấu tiện ích con (hoặc hình chữ nhật) bị bẩn và khi vòng lặp chính bị nhàn rỗi expose sự kiện sẽ được nhận nơi bạn có thể vẽ lại. Từ mô tả của bạn, có vẻ như các bản cập nhật đang diễn ra trên sự kiện expose để các API này có thể được sử dụng. Ngoài ra, bạn có thể kiểm tra this sample từ trang web cairo nơi bạn có thể thấy việc sử dụng gtk_widget_queue_draw_area.
tôi đã không sử dụng pygtk nhưng từ Google tôi thấy rằng các cuộc gọi tương ứng cho gtk_widget_queue_draw_areagtk.Widget.queue_draw_area & cho gdk_window_invalidate_rectgtk.gdk.Window.invalidate_rect
Hope this helps!

+0

Cảm ơn bạn đã trả lời! Thật không may, điều đó dường như không giải quyết được vấn đề. Trong thực tế, tôi đã có gtk.gdk.Window.invalidate_rect tất cả cùng, và nó là sự thật rằng nếu tôi rời khỏi đó ra sau đó vải không được cập nhật ở tất cả. Những gì tôi thấy khá lạ là thói quen vẽ của tôi vẽ màu trắng vải và sau đó vẽ các dòng trên đó, và bức tranh luôn được thực hiện, nhưng các dòng được hiển thị chỉ khi tôi cuộn các cửa sổ cuộn. Vì vậy, có vẻ như tiện ích con được cập nhật ít nhất một lần. – v923z

+0

@ v923z: Ah ok! Nó thực sự có vẻ giống như một trường hợp thiếu sự kiện phơi bày! Có âm thanh lạ mặc dù ... bạn đang cập nhật canvas trong expose sự kiện gọi lại tôi presume & canvas đang được cập nhật mong đợi cho một vài dòng bản vẽ mất tích, là như vậy? Nếu có thể, bạn có thể đăng một vài đoạn mã ... chúng tôi có thể cố gắng giúp đỡ –

+0

Cảm ơn bạn đã phản hồi! Tôi đã cập nhật bài đăng gốc của mình. – v923z

Các vấn đề liên quan