Python 在子线程原因中的TextCtrl上放置值不会导致';t始终工作,并导致随机分段故障

Python 在子线程原因中的TextCtrl上放置值不会导致';t始终工作,并导致随机分段故障,python,wxpython,Python,Wxpython,我正在尝试使用wxpython创建gui应用程序,但是TextCtrl元素出现了一些问题。我试图实现的效果是,用户将在文本字段(command)中输入一个命令,该命令可能会弹出一条出现在“(out)字段中的消息。一段时间后(本例中为0.7秒),消息将返回默认消息(“输出”)。我有两个问题: 消息并不总是出现 程序有时会因为分段错误而崩溃,我没有收到任何错误消息来处理它 我想这两者有某种联系,但我不知道为什么。在下面的示例中,我只键入“test”并等待原始消息出现。这两个问题都发生在这种情况下 我

我正在尝试使用wxpython创建gui应用程序,但是
TextCtrl
元素出现了一些问题。我试图实现的效果是,用户将在文本字段(
command
)中输入一个命令,该命令可能会弹出一条出现在“(
out
)字段中的消息。一段时间后(本例中为0.7秒),消息将返回默认消息(
“输出”
)。我有两个问题:

  • 消息并不总是出现
  • 程序有时会因为分段错误而崩溃,我没有收到任何错误消息来处理它 我想这两者有某种联系,但我不知道为什么。在下面的示例中,我只键入“test”并等待原始消息出现。这两个问题都发生在这种情况下

    我在这里发布了两个文件,作为最小的工作示例。文件号1,创建GUI

    import wx
    import os.path
    
    import os
    
    from threading import Thread
    from time import sleep
    from MsgEvent import *
    
    class MainWindow(wx.Frame):
        def __init__(self):
            super(MainWindow, self).__init__(None, size=(400,200),)
    #style=wx.MAXIMIZE)
            self.CreateInteriorWindowComponents()
            self.CreateKeyBinding()
            self.command.SetFocus()
            self.Layout()
    
        def Test(self):
            self.command.SetValue('open')
            self.ParseCommand(None)
    
    
        def PostMessage(self,msg):
            '''For its some reason, this function is called twice, 
            the second time without any input. I could'nt understand why. 
            For that, the test :if msg == None'''
            if msg == None: return 
            worker = MessageThread(self,msg,0.7,'OutPut')
            worker.start()
    
        def CreateKeyBinding(self):
            self.command.Bind(wx.EVT_CHAR,self.KeyPressed)
    
        def KeyPressed(self,event):
            char = event.GetUniChar()
            if char == 13 and not event.ControlDown(): #Enter
                if wx.Window.FindFocus() == self.command:
                    self.ParseCommand(event)
            else:
                event.Skip()
    
        def ParseCommand(self,event):
            com = self.command.GetValue().lower() #The input in the command field
    
            self.PostMessage(com)
    
        def CreateInteriorWindowComponents(self):
            ''' Create "interior" window components. In this case it is just a
                simple multiline text control. '''
            self.panel = wx.Panel(self)
    
            font = wx.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT)
            font.SetPointSize(12)
    
            self.vbox = wx.BoxSizer(wx.VERTICAL)
    
            #Out put field
            self.outBox = wx.BoxSizer(wx.HORIZONTAL)
            self.out = wx.TextCtrl(self.panel, style=wx.TE_READONLY|wx.BORDER_NONE)
            self.out.SetValue('OutPut')
            self.out.SetFont(font)
            self.outBox.Add(self.out,proportion=1,flag=wx.EXPAND,border=0)
            self.vbox.Add(self.outBox,proportion=0,flag=wx.LEFT|wx.RIGHT|wx.EXPAND,border=0)
            #Setting the backgroudn colour to window colour
            self.out.SetBackgroundColour(self.GetBackgroundColour())
    
    
            #Commands field
            self.commandBox = wx.BoxSizer(wx.HORIZONTAL)
            self.command = wx.TextCtrl(self.panel, style=wx.TE_PROCESS_ENTER)
            self.command.SetFont(font)
            self.commandBox.Add(self.command, proportion=1, flag=wx.EXPAND)
            self.vbox.Add(self.commandBox, proportion=0, flag=wx.LEFT|wx.RIGHT|wx.EXPAND, border=0)
    
            self.panel.SetSizer(self.vbox)
            return
    
    
    
    
        #Close the window
        def OnExit(self, event):
            self.Close()  # Close the main window.
    
    
    
    
    
    app = wx.App()
    frame = MainWindow()
    frame.Center()
    frame.Show()
    app.MainLoop()
    
    文件编号2,名为
    MsgThread.py
    处理事件

    import wx
    import threading 
    import time
    
    myEVT_MSG = wx.NewEventType()
    EVT_MSG = wx.PyEventBinder(myEVT_MSG,1)
    
    class MsgEvent(wx.PyCommandEvent):
        """ event to signal that a message is ready  """
        def __init__(self,etype,eid,msg='',wait=0,msg0=''):
            """ create the event object """
            wx.PyCommandEvent.__init__(self,etype,eid)
            self._msg = unicode(msg)
            self._wait_time = wait
            self._reset_message = unicode(msg0)
    
        def GetValue(self):
            """ return the value from the event """
            return self._msg
    
    
    
    class MessageThread(threading.Thread):
        def __init__(self,parent,msg='',wait=0,msg0=''):
            """ 
            parent - The gui object that shuold recive the value
            value - value to handle
            """
            threading.Thread.__init__(self)
            if type(msg) == int:
                msg = unicode(msg)
            self._msg = msg
            self._wait_time = wait
            self._reset_message = msg0
            self._parent = parent
            print self._msg
        def run(self):
            """ overide thread.run Don't call this directly, its called internally when you call Thread.start()"""
            self._parent.out.SetValue(unicode(self._msg))
            time.sleep(self._wait_time)
            self._parent.out.SetValue(self._reset_message)
            self._parent.MessageFlag = False
            event = MsgEvent(myEVT_MSG,-1,self._msg)
            wx.PostEvent(self._parent,event)
    

    什么是错误的

    除了3个函数(WX.CallAfter、WX.CallLater、WX.PostEvent)之外,WX Python不是线程安全的

    因此,基本上你要做的是确保你从不直接从子线程中调用任何小部件。您可以使用events或CallAfter

    您可能还需要检查以下内容:

    洛克拉