2014-10-18 19 views
0

我試圖創建一個使用wxpython的gui應用程序,並且我得到了一些與TextCtrl元素有關的問題。我嘗試實現的效果是,用戶將輸入命令到文本字段(command),該命令可能會彈出出現在'(out)「字段中的消息。經過一段時間(本例中爲0.7秒)後,該消息將回到默認消息("OutPut")。我有兩個問題:將值放在TextCtrl中的子線程原因並不總是工作並導致隨機分段錯誤

  1. 該消息並不總是顯示。
  2. 該程序有時因分段錯誤而崩潰,並且我沒有收到任何錯誤消息來處理該問題。

我想這兩者有某種關係,但我不知道爲什麼。在下面的例子中,我只輸入「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) 

什麼是錯誤的?

回答

相關問題