pygtk中处理主界面与后台连接的方法

    这几日学着用pygtk做了一个下载歌曲的小工具,但在实际完成过程中产生了一个让我困扰的问题,pygtk并不像java一样可以将实时产生的数据返回 给主界面的progressbar widget,于是造成的结果就是,只要开始下载,主界面就变为“未反应” 但实际上下载已经开始。在google无数次后终于找到了一个凑合的解决方法 尽管不是很完美,但基本上可以解决问题。现在贴出来,供大家了解一下。


You have created a progress bar inside a window, then you start running a loop that does some work:

    while work_left:
        ...do something...
        progressbar.set_fraction(...)

You will notice that the window doesn't even show up, or if it does the progress bar stays frozen until the end of the task. The explanation is simple: gtk is event driven, and you are stealing control away from the gtk main loop, thus preventing it from processing normal GUI update events.

The simplest solution consists on temporarily giving control back to gtk every time the progress is changed:

    while work_left:
        ...do something...
        progressbar.set_fraction(...)
        while gtk.events_pending():
            gtk.main_iteration()

Notice that with this solution, the user cannot quit the application (gtk.main_quit would not work because of new loop [gtk.main_iteration()]) until your heavy_work is done.

Another solution consists on using gtk idle functions, which are called by the gtk main loop whenever it has nothing to do. Therefore, gtk is in control, and the idle function has to do a bit of work. It should return True if there's more work to be done, otherwise False.

The best solution (it has no drawbacks) was pointed out by James Henstridge. It is taking advantage of python's generators as idle functions, to make python automatically preserve the state for us. It goes like this:

    def my_task(data):
        ...some work...
        while heavy_work_needed:
            ...do heavy work here...
            progress_label.set_text(data) # here we update parts of UI
            # there's more work, return True
            yield True
        # no more work, return False
        yield False

   def on_start_my_task_button_click(data):
        task = my_task(data)
        gobject.idle_add(task.next)

The 'while' above is just an example. The only rules are that it should yield True after doing a bit of work and there's more work to do, and it must yield False when the task is done.

More on generators:

Generators are objects that are defined as functions, and when called produce iterators that return values defined by the body of the function, specifically yield statements.

The neat thing about generators are not the iterators themselves but the fact that a function's state is completely frozen and restored between one call to the iterator's next() and the following one. This is just the right thing we need to turn our functions into pseudo-threads, without actually incurring the wrath of the gods of software.
More:
http://www.gnome.org/~gjc/gtasklet/gtasklets.html
主要的办法就是使用gobject的idle_add

更好的办法也找到了,就是lazybones前辈的gmbox的解决方法,感觉他的更好一点,有兴趣的可以去看看他的gmbox代码 地址是 http://gmbox.googlecode.com/files/gmbox-0.2.tar.gz 有兴趣的可以下载下来看看


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值