当在WxPython中连续写入WriteText(AppendText,SetLabel等)时,是否存在某种打印缓冲区溢出?

时间:2014-05-03 20:52:39

标签: python wxpython

我有一些文本在输出上有点连续(有些=在实际应用程序中每两秒左右)。

当只有print进入终端时,无论我保持运行循环多长时间,一切都还可以。

然而,当将打印引导到wx帧时,打印动作本身就很顺利,这里没问题,但是如果我保持运行循环超过10-20个循环,我将无法再关闭通常的窗口(在此示例中为鼠标或Ctrl + F4,但如果我构造一个显式的Exit事件菜单,则相同)。线程中的操作停止,但应用程序挂起 - 它只能由操作系统(在我的情况下为Windows)关闭,并强制关闭/等待程序响应"对话。但是,当终端窗口处于焦点时,可以使用Ctrl + C立即关闭它。看起来有些东西填满了过多的文字并锁定了结束过程。

在多行WriteText窗口中使用AppendTextwxTextCtrl,或在下面的测试代码中使用SetLabel。

在此测试中,如果我在发射后几乎立即关闭wx窗口,它会很好地关闭。如果我继续运行循环更长时间(或通过注释掉两个time.sleep()行),那么只要尝试关闭窗口,挂起就会成功。

我在这里缺少什么? (我有什么必须冲洗吗?)

编辑嗯,这个问题可能与"线程安全方法"有关,如简要描述here。将在这个方向上做一些测试,必须找出每个wx.CallAfterwx.CallLaterwx.PostEvent的正确用法。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import wx
import time
import threading

class TestFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.sometext = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY)
        self.thread = None
        self.alive = threading.Event()
        self.__set_properties()
        self.__do_layout()
        self.__attach_events()
        self.StartThread()

    def __set_properties(self):
        self.SetTitle("test")

    def __do_layout(self):
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.sometext, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL, 0)
        self.SetSizer(sizer)
        sizer.Fit(self)
        self.Layout()

    def __attach_events(self):
        self.Bind(wx.EVT_CLOSE, self.OnClose)

    def OnClose(self, event):
        """ stop & close on system window close """
        self.StopThread()
        self.Destroy()

    def StartThread(self):
        """ start the thread """
        self.thread = threading.Thread(target=self.TestThread)
        self.thread.setDaemon(1)
        self.alive.set()
        self.thread.start()

    def StopThread(self):
        """ stop the thread, wait util it is finished """
        if self.thread is not None:
            self.alive.clear()
            self.thread.join()
            self.thread = None

    def TestThread(self):
        """ main thread """
        while self.alive.isSet():
            self.sometext.SetLabel("Hello")
            time.sleep(0.5)
            self.sometext.SetLabel("Python")
            time.sleep(0.5)

class MyApp(wx.App):
    def OnInit(self):
        wx.InitAllImageHandlers()
        frame = TestFrame(None, -1, "")
        self.SetTopWindow(frame)
        frame.Show(1)
        return 1

if __name__ == "__main__":

    app = MyApp(0)
    app.MainLoop()

1 个答案:

答案 0 :(得分:0)

我已使用AppendtText更改了每个SetLabal。我不知道为什么,但SetLabel功能对我来说无法正常工作。

几秒钟后,应用程序将停止工作。这是我的错误输出:

(python:14099): Pango-CRITICAL **: pango_layout_get_iter: assertion 'PANGO_IS_LAYOUT (layout)' failed
Segmentation fault

之后我使用了CallAfter函数http://wiki.wxpython.org/CallAfter,应用程序开始正常为我工作。我的TestThread版本:

def TestThread(self):
        """ main thread """
        while self.alive.isSet():
            wx.CallAfter(self.sometext.AppendText, "Hello")
            time.sleep(0.5)
        wx.CallAfter(self.sometext.AppendText, "Python") 
        time.sleep(0.5)
        wx.CallAfter(self.sometext.Clear)

我希望这对你有所帮助。