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