我正在尝试将一个gtkProgressBar添加到我为R脚本创建的一个小接口中(使用RGtk2包)。
如果我做了一些简单的事情,如:
for (i in 1:50)
{
gtkProgressBarSetFraction(progress, i/50)
Sys.sleep(1)
}一切运行顺利,该栏每秒钟更新一次。
然而,当我进入实际的代码时,我有一个循环,在这个循环中,我执行以下操作
for(i in 1:1000)
{
gtkProgressBarSetFraction(progress, i/1000)
#do some heavy computation here
}这里的问题是接口“冻结”,进度条只在循环结束时更新,因此完全失败了它的使用.
我是不是漏掉了什么?我如何周期性地“唤醒”接口,使其刷新?
谢谢尼科
编辑:好的,我解决了这个问题,但我仍然不明白发生了什么。我在Sys.sleep之后添加了一个gtkProgressBarSetFraction调用,现在接口高兴地更新了。为了减少“浪费的时间”,我刚刚做了Sys.sleep(0.0001) (因此,对于1000个周期,我只有~0.1-1秒的计算时间,这是可以接受的)。有人能解释为什么会发生这种事吗?
发布于 2010-09-29 13:20:48
处理一个事件:gtkMainIterationDo(FALSE)。处理所有挂起的事件:while(gtkEventsPending()) gtkMainIteration()。
这段代码之所以需要,是因为R和Gtk事件循环的交互方式--在每一点上,R或Gtk都是控制的,并且需要手动地将控制传递给对方。Sys.sleep是这样做的一种方式,而这些特定于RGtk2的函数是另一种方式。
发布于 2010-09-29 12:22:03
几乎所有的GUI都使用称为事件循环的概念。程序有一些消息队列,并在从队列中选择新消息并执行它们的过程中被无限循环。队列由从OS接收的一些事件填充,如键笔画、鼠标单击、调整窗口大小等,以及程序本身抛出的消息。它看起来不是这样的,但是R也有它自己的事件循环(对于图形,但不仅仅是,它是由RGtk扩展的,虽然这通常很复杂,但我不打算详细介绍)。
现在,当您调用gtkProgressBarSetFraction时,进度条不会直接更新,但是将创建请求重绘的消息并将其推送到队列中。因此,在被事件循环迭代选中之前,它不会产生任何效果,但这种情况在R完成脚本的执行之前是不会发生的,或者当循环异常地被触发时(由内部超时或某些函数(如Sys.sleep())触发)。
https://stackoverflow.com/questions/3820402
复制相似问题