多个 wx.Yield() 替代方案

2 投票
2 回答
3849 浏览
提问于 2025-04-17 21:47

我现在有一个用wxpython做的图形界面应用,它会读取一个不断增长的文本文件,并把内容显示在一个wx.TextCtrl窗口里。我需要同时运行两个这样的窗口,但显然我遇到了一个问题,就是出现了“wxYield被递归调用”的错误。请问有没有简单的方法可以替代wx.Yield,让我能够同时运行多个窗口呢?

self.running_log = wx.TextCtrl(self, -1, pos=(5, 5), size=(875,605),
                                       style = wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL)

while True:
    wx.Yield()
    fileSize = os.path.getsize(logPath)
    if fileSize > lastSize:
        lines = infile.readlines()
        newLines = 0
        for line in lines[lastLineIndex:]:
            newLines += 1
            print line.rstrip()
        self.running_log.AppendText(line)

2 个回答

0

wx.SafeYield() 不是为了专门解决这个问题而设计的吗?

比如,可以看看这里 点击这里查看链接

1

你可以看看 wxPython 的维基页面:LongRunningTasks。在那儿你会看到两种替代使用 wxYield 的方法:线程处理或者把你的处理放在 EVT_IDLE 处理器里。

不过既然你已经在用 wxYield,我建议你可以先试试一个解决方案,而不是马上换别的:使用一个标志来表示你是否已经在运行。如果这个标志为真,就不要让代码再次执行 wxYield。

当你调用 wx.Yield() 时,wxPython 会接管控制权,处理它需要处理的任何事件。当处理完成后,你的长时间运行的任务会在你调用 yield 之后继续进行。所以你可以把所有的处理放在一个循环里,让它在那儿转圈,只要需要就行。通过添加一个标志,你可以限制代码的入口点,只在 yield 的地方。当你的处理完成后,你通过切换标志来释放你的“锁”,这样代码的入口点就变回实际的方法调用了。

大致可以这样写:

if not running:
    running = True
    while True:
        wx.Yield()
        fileSize = os.path.getsize(self.logPath)
        if fileSize > lastSize:
            lines = infile.readlines()
            newLines = 0
            for line in lines[lastLineIndex:]:
                newLines += 1
                self.running_log.AppendText(line)
        # When you are finished, set running to False and break

注意,检查一下 getsize 被调用的频率可能是个好主意。如果调用得太频繁,你可以通过确保经过了一段短时间来限制它,以避免过多的调用拖慢你的系统。

撰写回答