所以我使用wxpython为程序制作GUI。我还在这个程序中嵌入了matplotlib图。
我的问题是,当我尝试使用draw()不断更新plot时,我的程序变得不负责任,但是matplotlib图仍在更新。
这是我的一部分代码,以及我如何执行所有这些,
def update(self, e):
if self.liveMode:
self.tune.plot(); # new plot
self.canvas.draw();
self.startLive(e);
def startLive(self, e):
self.liveMode = False;
refFreq = 500e6 / 80;
qx = self.pv1.get();
qy = self.pv2.get();
self.tune.newWorkingpoint(refFreq/qx, refFreq/qy);
self.tune.liveUpdate();
time.sleep(0.3);
self.update(e);
当在我的程序中按下'live mode'按钮时,'update'方法被调用。我绘制了所有背景线,然后反复从其他地方获取新的点值,并将其绘制为图形上的圆圈,并使用draw()方法进行更新。当然,因为我本质上是在一个连续循环中,在这个过程完成之前,没有其他任何东西可以工作。我的目标是放一个"停止"按钮来停止这个实时绘图循环,但是因为当matplotlib绘图时一切都变得无响应,所以没有按钮可点击,我必须停止编译以停止程序。
还有别的办法吗?我已经研究过线程,但我得到同样的问题与此。
编辑 : ---------------------------------------------------------------------------------------------------------------------------- 我有使用这个页面作为指导工作。然而,几秒钟后,我得到这个致命的错误,我的程序崩溃了。'python2.7: X服务器上的致命IO错误11(资源暂时不可用):0.0.'
下面是我实现的方法。当开始按钮被按下时,'startlive'开始,当停止按钮被按下时,'stoplive'开始。一切工作正常,我的matplotlib图被正确更新,没有我的wxpython GUI变得无响应。问题是几秒钟后我得到致命错误,我的程序崩溃了。我认为这很可能与canvas.draw()方法有关,该方法在线程内更新matplotlib。对于如何解决这个问题有什么想法吗?
def startLive(self, e):
self.livemode.change(True);
self.worker = CountingThread(self.panel,self.tune,self.canvas,self.livemode, self.pv1, self.pv2);
self.worker.start();
def stopLive(self, evt):
self.livemode.change(False);
class CountingThread(threading.Thread):
def __init__(self, parent, tune, canvas, livemode, pv1, pv2):
threading.Thread.__init__(self)
self._parent = parent;
self._tune = tune;
self._canvas = canvas;
self._livemode = livemode;
self._pv1 = pv1;
self._pv2 = pv2;
def run(self):
refFreq = 500e6 / 80;
i=0;
while self._livemode.get():
self._tune.newWorkingpoint(refFreq / self._pv1.get(), refFreq / self._pv2.get());
self._tune.liveUpdate();
self._canvas.draw();
time.sleep(0.2);
i+=1;
print(i)
class livemode:
livemode=False;
def __init__(self):
self.livemode = False;
def change(self, livemode):
self.livemode = livemode;
def get(self):
return self.livemode;
-------------------------------- 编辑 ---------------------------------如果有人感兴趣的话,我已经解决了这个问题。
在线程运行方法中,我删除了循环,只保留了一个'updating'实例。更新后,wx。PostEvent被调用,它在包含wx的主类中调用一个方法。通过调用draw()来更新绘图的应用程序。在此之后,重新启动线程并重复相同的进程。我的GUI继续工作,绘图速度仍然非常快。重要的方法如下,
Threading.start()被调用,下面执行
def run(self):
refFreq = 500e6 / 80;
self._tune.newWorkingpoint(refFreq / self._pv1.get(), refFreq /self._pv2.get());
self._tune.liveUpdate();
evt = CountEvent(myEVT_PLOT, -1);
wx.PostEvent(self._parent, evt);
wx。PostEvent在main wx中调用以下新方法。应用程序类,
def continueLive(self, evt):
if self.livemode.get():
self.canvas.draw();
self.startLive(evt)
剧情更新,整个过程重新开始。
这个方法保持GUI的响应性和绘图速度不会减慢。
我认为这可能是堆栈问题。你的更新循环是递归的,堆栈有一个有限的大小(每个函数调用被推入堆栈,并在函数返回时删除)。
您应该将其更改为迭代版本。
def update(self, e):
if self.liveMode:
self.tune.plot(); # new plot
self.canvas.draw();
#self.startLive(e); # causes endless recursion
def startLive(self, e):
while (self.isInLiveMode): # some flag here that gets set to False once the mode is deactivated
self.liveMode = False;
refFreq = 500e6 / 80;
qx = self.pv1.get();
qy = self.pv2.get();
self.tune.newWorkingpoint(refFreq/qx, refFreq/qy);
self.tune.liveUpdate();
time.sleep(0.3);
self.update(e);
我假设self。liveMode应该是那个标志
希望这有帮助,LG丹尼尔