强制PyGtk主要重绘

时间:2013-01-25 02:24:57

标签: python python-2.7 gtk pygtk gobject

我有这样的UI结构:
1x Horizo​​ntalBox - > 8x VerticalBox - > 2x部分(GObject) - > 1x RectangleWidget(gtk.DrawingArea)

这只是一个包含两行16个开罗矩形的表格。

cairo矩形小部件本身是gtk.DrawingArea的子类,并且有一个expose-handler。

我现在重写了程序,数据结构和UI现在完全分开了。有一个线程在后台运行,更新数据结构。在fornt中调用了UI gobject.threads_init()。超过100毫秒gobject.timeout_add(100, self.update_widget)后,主要发出一个信号,该信号仅由第一个小部件接收。

这里是expose-handler:

def OnDraw(self, widget, event):    
    # self.window / widget.window works both
    ctx = widget.window.cairo_create()
    ctx.save()

    rect = self.get_allocation()    
    ctx.rectangle(50, 0,  30, rect.height)
    ctx.set_source_rgb(*self._BACKGROUND_RGB)
    ctx.fill()

    ctx.rectangle(0, rect.height * (1. - self.section.GetLevel()), rect.width, rect.height)
    ctx.clip()        
    ctx.set_source_surface(self.source, 0, 0)   
    ctx.paint()
    ctx.restore()

    return False
#_____________________________________________________________________

def update_widget(self):
    rect = self.get_allocation()        
    self.window.invalidate_rect(rect, False)
    while gtk.events_pending():
        gtk.main_iteration(False)
    return True
#_____________________________________________________________________

请注意:
如果我最小化并恢复窗口,小部件将收到gsignal并进行更新。

我尝试了不同的方法。包括线程,不同的信令......所有方法都会导致上述相同的行为。

如何强制gtk.main返回并重绘其他小部件?

2 个答案:

答案 0 :(得分:2)

尝试mainHbox.queue_draw()

如果它不起作用,则迭代所有RectangleWidget对象并重绘:

for vbox in mainHbox.get_children():
    for hbox in vbox.get_children():
        for widget in hbox.get_children():
            widget.queue_draw()

如果您使用的是Table,那就更容易了......

答案 1 :(得分:0)

  

超时100ms后gobject.timeout_add(100,self.update_widget)

尝试在没有gobject.timeout_add()的情况下制作GUI线程,并在另一个线程[s]中进行所有其他计算。

gobject.timeout_add看起来像是分离的线程,gtk无法正常使用它。

我的部分程序(可行):

def init_tr_modules(self):
    window = gtk.Window(gtk.WINDOW_TOPLEVEL)
    window.set_title("Checking internet connection")
    window.set_border_width(2)
    window.set_icon(app_gui.icon)
    window.set_geometry_hints(None, 510, 27)
    vbox = gtk.VBox(False, 1)
    vbox.set_border_width(1)
    window.add(vbox)
    pbar = gtk.ProgressBar()
    vbox.pack_start(pbar, False, False, 1)
    window.set_position(gtk.WIN_POS_CENTER)
    window.set_resizable(False)
    pbar.set_text("Wait")
    pbar.set_pulse_step(0.01)
    window.show_all()
    tr_thread = \
         threading.Thread(target = self.init_tr_services)
    tr_thread.start()
    while self.queue.qsize() == 0:
        while gtk.events_pending():
            gtk.main_iteration(False)
        pbar.pulse()
        sleep(0.05)
    while self.queue.qsize():
        self.queue.get()
    window.set_title("Get list")
    pbar.set_fraction(0.005)
    while gtk.events_pending():
        gtk.main_iteration(False)
    for i in self.tr_services:
        pbar.set_text(i.service.get_service_name())
        tr_thread = \
            threading.Thread(target = i.service.renew_list)
        tr_thread.start()
        while self.queue.qsize() == 0:
            while gtk.events_pending():
                gtk.main_iteration(False)
        while self.queue.qsize():
            self.queue.get()
        new_val = pbar.get_fraction() + (1.0-0.006) / len(self.tr_services)
        pbar.set_fraction(new_val)
    window.destroy()
#end def

所有非gui动作都隐藏在非主线程中。主线 - 桂。 希望如果我正确理解问题,这会有所帮助:)