2

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

这只是一个两行 16 个 cairo 矩形的表格。

cairo 矩形部件本身是 gtk.DrawingArea 的子类,并且有一个暴露处理程序。

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

这里是暴露处理程序:

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 返回并重绘其他小部件?

4

2 回答 2

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,那就更容易了......

于 2013-07-29T17:58:40.437 回答
0

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

尝试在另一个线程中创建没有 gobject.timeout_add() 和所有其他计算的 GUI 线程。

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 操作都隐藏在非主线程中。主线程 - gui。如果我正确理解问题,希望这会有所帮助。:)

于 2013-07-09T08:56:13.073 回答