持续读取文件并相应地更新Python GTK应用程序

0 投票
3 回答
1063 浏览
提问于 2025-04-17 07:31

我正在做一个手势识别的项目。有一个C语言程序,它从视频输入中捕捉手势并把这些手势写入文件。现在,我有一个用Python写的图像查看器 - GTK。这个查看器会根据手势切换到下一个或上一个窗口。这个持续读取文件和更新应用程序的过程是这样定义的:

def ai(self):
        if self.mtime!=os.stat("input.txt").st_mtime:
            self.mtime=os.stat("input.txt").st_mtime
            inp=open("input.txt", "r");
            line=inp.read()
            if len(line)!=0:
                line=line[0:len(line)-1]
                for x in line.split(' '):
                    y=x.split('-')
                    if(y[1]=="R"):
                        self.next()
                        print "Move Right"
                    elif(y[1]=="L"):
                        self.prev()
                        print "Move Left"
        time.sleep(1)
        print "WakeUp"
        self.ai()

现在,如果我把这里的递归调用注释掉,那么应用程序在读取当前文件并更新图像后就能正常工作。当然,这样的话,它就不会再更新了。

但是如果我把递归调用取消注释,控制台会一直工作,但图像查看器应用程序就不再响应了。

有没有什么办法可以实现这个功能?有没有什么事件可以绑定这个 ai() 函数,让它在每次触发这个事件时检查文件更新……任何帮助都非常感谢。

3 个回答

1

因为你在使用 gtk,你可以利用 gio 模块来帮你监控文件的状态,而不是自己写一个定时检查文件状态的方案:

monitor = gio.File(filename).monitor()
monitor.connect('changed', file_changed_cb)

请注意,你可以把 changed 信号连接到你的回调函数,这样就可以在文件状态变化时执行你需要的更新。

2

免责声明:我对使用pygtk完全没有经验。

我想要让这个工作正常,你需要让GTK的事件循环来调用你的代码(因为你递归调用的方式让控制权永远不会回到事件循环)。

你可能有两个选择:

  • 要么设置一个定时器事件,让你的方法每隔nnn毫秒被调用一次(教程
  • 要么使用某种空闲事件,让你的方法在GTK程序空闲的时候被调用(教程
6

我不太确定我是否理解你的意思,但我觉得你想要做的是在你的主GTK循环中安排一个调用ai()的任务,这样你的程序就能定期检查是否有输入。

如果这正是你想要的,你有两个选择:要么定期安排这个调用,要么在程序空闲的时候安排这个调用(也就是程序没有在做其他事情的时候)。

你的代码大概应该是这样的:

gobject.idle_add(callback, ...)  #execute callback when idle
gobject.timeout_add(interval, callback, ...)  #execute callback every interval millisecs

相关的文档可以在这里找到,不过现在好像有服务器错误。以下是相关的内容:

gobject.idle_add()这个函数会把一个函数(由回调指定)添加到默认的主循环中,当没有更高优先级的事件待处理时就会调用这个函数。这个函数的优先级是默认的空闲优先级,gobject.PRIORITY_DEFAULT_IDLE。你可以在回调后面指定额外的参数。如果回调返回FALSE,它会自动从事件源列表中移除,以后就不会再被调用了。

gobject.timeout_add()这个函数会设置一个函数(由回调指定),在规定的时间间隔(由interval指定,默认优先级是gobject.PRIORITY_DEFAULT)内定期调用。你也可以在回调后面指定额外的参数。空闲优先级可以用关键字-值对的形式指定,关键字是"priority"。

需要注意的是:如果你希望回调函数保持在调度器中,就要让它返回True,否则它只会执行一次。

希望这些信息对你有帮助!

撰写回答