wx.量规无法在Windows中更新超过25%,可在Linux中工作

2024-06-07 01:43:45 发布

您现在位置:Python中文网/ 问答频道 /正文

在wxPython和跨平台兼容性方面,我似乎只有麻烦:(

我有以下功能。当用户单击一个按钮时调用它,它执行一些可能需要一段时间的工作,在此期间状态栏中会显示一个进度表。在

def Go(self, event):       
    progress = 0
    self.statbar.setprogress(progress)
    self.Update()

    # ...

    for i in range(1, numwords + 1):
        progress = int(((float(i) / float(numwords)) * 100) - 1)
        self.wrdlst.append(words.next())
        self.statbar.setprogress(progress)
        self.Update()

    self.wrdlst.Refresh() 

    # ...

    progress = 100
    self.PushStatusText(app.l10n['msc_genwords'] % numwords)        
    self.statbar.setprogress(progress)

显然,在Linux下需要调用self.Update(),否则在函数退出之前,规范不会更新,这使得它有点毫无意义。这些调用在Windows下似乎没有效果(至少是win7)。在

整个过程在Linux下运行得很好(通过调用Update()),但是在windows7上,这个指标似乎在函数退出之前的20-25%左右停止。因此,它会按它应该的方式移动,直到达到~25%,然后仪表会无缘无故地停止移动,但功能继续良好,并以适当的输出退出。在

在我试图找出问题的过程中,我尝试在更新循环内部的仪表之前插入一条print progress行,认为progress的值可能不是我认为的那样。令我大吃一惊的是,这个量表现在正常工作,但是当我把它取下的时候,它就停止工作了。我也可以用调用time.sleep(0.001)来代替打印,但是即使在这么短的睡眠时间内,这个过程仍然几乎停止,如果我再降低它,问题就会再次出现,因此它几乎没有什么帮助。在

我不知道发生了什么,也不知道如何解决它,但我想不知怎么的,Windows下的东西移动得太快了,以至于progress在一段时间后无法正确更新,而只是保持在一个固定值(~25)。我不知道为什么会这样,但是,这对我来说毫无意义。当然,print和{}都不是好的解决方案。即使我打印出“nothing”,Windows仍然会为不存在的输出打开另一个窗口,这很烦人。在

如果你需要更多的信息或代码,请告诉我。在

编辑:好的,这里有一个正在工作的应用程序(至少对我来说)有问题。时间还很长,但我试着删掉所有与手头问题无关的东西。在

它可以在Linux上运行,就像完整的应用程序一样。在Windows下,它要么失败要么工作,这取决于Go函数中numwords的值。如果我把它的值增加到1000000(一百万),问题就消失了。我怀疑这可能取决于系统,所以如果它适合您,请尝试调整numwords的值。这也可能是因为我更改了它,使其Append()是一个静态文本,而不是像在原始代码中那样调用生成器。在

不过,对于我来说,当前值为numwords(100000),它在Windows上确实失败了。在

^{pr2}$

编辑2:下面是代码的更简单版本。我想我不能把它弄小很多。我还是有问题。我可以在IDLE中运行它,也可以直接在Windows中双击.py文件来运行,无论哪种方式都是一样的。在

我尝试使用numwords的各种值。问题似乎并没有像我第一次说的那样消失,相反,当我增加numwords时,量规在print被调用之前会越来越远。以目前的价值1.000.000,这个较短的版本达到大约50%。在上面的较长版本中,值1.000.000达到大约90%,值100.000达到大约25%,而值10.000只达到10%左右。在

在下面的版本中,一旦调用print,进程将继续并达到99%,即使此时循环必须已经结束。在原始版本中,对self.wrdlst.Refresh()的调用(当numwords为高值时需要几秒钟)一定导致了仪表暂停。所以我认为会发生这样的情况:在回路中,仪表只到达某一点,当回路退出时,功能继续工作,而仪表保持静止;当功能退出时,仪表继续工作,直到达到99%。因为打印语句不需要太多时间,下面的版本使它看起来像就像压力计从0%平稳地移动到99%,但是print则相反。在

import wx

class MainFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super(MainFrame, self).__init__(*args, **kwargs)        
        self.panel = wx.Panel(self)        
        self.gobtn = wx.Button(self.panel, label="Go")
        self.prog = wx.Gauge(self, style=wx.GA_HORIZONTAL)
        wrap = wx.BoxSizer()
        wrap.Add(self.gobtn, 0, wx.EXPAND|wx.ALL, 10)
        wrap.Add(self.prog, 0, wx.EXPAND|wx.ALL, 10)
        self.panel.SetSizer(wrap)
        self.panel.Fit()
        self.SetInitialSize()        
        self.Bind(wx.EVT_BUTTON, self.Go, self.gobtn)

    def Go(self, event):        
        numwords = 1000000
        self.prog.SetValue(0)
        for i in range(1, numwords + 1):
            progress = int(((float(i) / float(numwords)) * 100) - 1)
            self.prog.SetValue(progress)
        print "Done"

if __name__ == "__main__":
    app = wx.App()
    frame = MainFrame(None)
    frame.Show()
    app.MainLoop()

Tags: self功能版本gowindows仪表updatefloat
1条回答
网友
1楼 · 发布于 2024-06-07 01:43:45

因此,实际上,您正在通过长时间运行的任务阻塞GUI线程。在某些平台和/或计算机上,它可能运行良好,也可能无法正常运行。在

import wx
from wx.lib.delayedresult import startWorker

class MainFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super(MainFrame, self).__init__(*args, **kwargs)        
        self.panel = wx.Panel(self)        
        self.gobtn = wx.Button(self.panel, label="Go")
        self.prog = wx.Gauge(self, style=wx.GA_HORIZONTAL)
        self.timer = wx.Timer(self)

        wrap = wx.BoxSizer()
        wrap.Add(self.gobtn, 0, wx.EXPAND|wx.ALL, 10)
        wrap.Add(self.prog, 0, wx.EXPAND|wx.ALL, 10)
        self.panel.SetSizer(wrap)
        self.panel.Fit()
        self.SetInitialSize()        

        self.Bind(wx.EVT_BUTTON, self.Go, self.gobtn)
        self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)


    def Go(self, event):
        # Start actual work in another thread and start timer which 
        # will periodically check the progress and draw it
        startWorker(self.GoDone, self.GoCompute)
        self.progress = 0
        self.timer.Start(100)

    def OnTimer(self, event):
        # Timer draws the progress
        self.prog.SetValue(self.progress)

    def GoCompute(self):
        # This method will run in another thread not blocking the GUI
        numwords = 10000000
        self.prog.SetValue(0)
        for i in range(1, numwords + 1):
            self.progress = int(((float(i) / float(numwords)) * 100) - 1)

    def GoDone(self, result):
        # This is called when GoCompute finishes
        self.prog.SetValue(100)
        self.timer.Stop()
        print "Done"

if __name__ == "__main__":
    app = wx.App()
    frame = MainFrame(None)
    frame.Show()
    app.MainLoop()

还要注意,与您的例子相反:

  • 单击后,按钮将返回到未拾取状态
  • 你可以移动窗户,它不会冻结

根据经验,每一个看起来像这样的方法应该只运行几毫秒。在

编辑:我在Windows7上观察到的另一件事。在您调用self.prog.SetValue()时,仪表开始增长,并在一段时间内增长到指定值。它不会“跳”到那个值,而是缓慢增长,达到设定值。这似乎是Windows7的功能。我不得不关闭性能选项中的“动画控件和窗口内的元素”来消除这种行为。在

相关问题 更多 >