2016-09-21 203 views
0

我有一段代碼必須每隔100ms執行一次並更新GUI。當我更新GUI時 - 我按下一個按鈕,該按鈕調用一個線程,然後調用目標函數。目標函數使用pub sub將消息返回給GUI線程,如下所示。GUI的頻繁更新WxPYTHON

wx.CallAfter(pub.sendMessage, "READ EVENT", arg1=data, arg2=status_read) # This command line is in my target function 

     pub.subscribe(self.ReadEvent, "READ EVENT") # This is in my GUI file - whihc calls the following function 

def ReadEvent(self, arg1, arg2): 
     if arg2 == 0: 
      self.MessageBox('The program did not properly read data from MCU \n Contact the Program Developer') 
      return 

     else: 
      self.data = arg1 

      self.firmware_version_text_control.Clear() 
      #fwversion = '0x' + ''.join('{:02X}'.format(j) for j in reversed(fwversion)) 
      self.firmware_version_text_control.AppendText(str(SortAndDecode(self.data, 'FwVersion'))) 
      # Pump Model 
      self.pump_model_text_control.Clear() 
      self.pump_model_text_control.AppendText(str(SortAndDecode(self.data, 'ModelName'))) 
      # Pump Serial Number 
      self.pump_serial_number_text_control.Clear() 
      self.pump_serial_number_text_control.AppendText(str(SortAndDecode(self.data, 'SerialNum'))[:10]) # Personal Hack to not to display the AA , AB and A0 
      # Pressure GAIN 
      self.gain_text_control.Clear() 
      self.gain_text_control.AppendText(str(SortAndDecode(self.data, 'PresGain'))) 
      # Pressure OFFSET Offset 
      self.offset_text_control.Clear() 
      self.offset_text_control.AppendText(str(SortAndDecode(self.data, 'PresOffset'))) 
      #Wagner Message: 
      #self.status_text.SetLabel(str(SortAndDecode(self.data, 'WelcomeMsg'))) 
      # PUMP RUNNING OR STOPPED 

      if PumpState(SortAndDecode(self.data, 'PumpState')) == 1: 
       self.led6.SetBackgroundColour('GREEN') 
      elif PumpState(SortAndDecode(self.data, 'PumpState')) == 0: 
       self.led6.SetBackgroundColour('RED') 
      else: 
       self.status_text.SetLabel(PumpState(SortAndDecode(self.data, 'PumpState'))) 
      # PUMP RPM 
      self.pump_rpm_text_control.Clear() 
      if not self.new_model_value.GetValue(): 
       self.pump_rpm_text_control.AppendText("000") 
      else: 
       self.pump_rpm_text_control.AppendText(str(self.sheet_num.cell_value(self.sel+1,10)*(SortAndDecode(self.data, 'FrqQ5'))/65536)) 
      # PUMP PRESSURE 
      self.pressure_text_control.Clear() 
      self.pressure_text_control.AppendText(str(SortAndDecode(self.data, 'PresPsi'))) 
      # ON TIME -- HOURS AND MINUTES --- EDITING IF YOU WANT 
      self.on_time_text_control.Clear() 
      self.on_time_text_control.AppendText(str(SortAndDecode(self.data, 'OnTime'))) 
      # JOB ON TIME - HOURS AND MINUTES - EDITING IF YOU WANT 
      self.job_on_time_text_control.Clear() 
      self.job_on_time_text_control.AppendText(str(SortAndDecode(self.data, 'JobOnTime'))) 
      # LAST ERROR ----- RECHECK THIS AGAIN 
      self.last_error_text_control.Clear() 
      self.last_error_text_control.AppendText(str(SortAndDecode(self.data, 'LastErr'))) 
      # LAST ERROR COUNT --- RECHECK THIS AGAIN 
      self.error_count_text_control.Clear() 
      self.error_count_text_control.AppendText("CHECK THIS") 

正如你可以看到我的READEVENT是非常大的,它需要一段時間的GUI採取足夠的時間成功地做這些事情。這裏我的問題是,當我的GUI更新TEXTCTRL的值時,它沒有響應 - 我什麼也做不了。我不能按下按鈕或輸入數據或其他任何東西。我的問題是,如果我有更好的方式來做到這一點,所以我的GUI不會無反應。我不知道如何將它放在不同的線程中,因爲所有的小部件都在主GUI中。但是這也需要每隔100ms創建一次線程 - 這太可怕了。任何建議都會非常有幫助。

回答

0

幾點建議:

  1. 多久SortAndDecode走?那麼str()的結果呢?這些可能是在工作者線程而不是UI線程中保持該處理的合適候選者,並將這些值傳遞給預先進行了排序和解碼的UI線程。

  2. 通過調用ChangeValue而不是ClearAppendText,可以在每次迭代中節省一點時間。爲什麼兩個函數調用每個文本部件而不是一個?與其他Python代碼相比,函數調用在Python中相對較爲昂貴。

  3. 如果可能會發送最後一次迭代發送的相同值,那麼添加與舊值匹配的新值的檢查並跳過小部件的更新可能會節省大量時間。與單獨使用相比,更新小部件值非常昂貴。

  4. 除非有100ms更新的硬性要求,否則您可能想嘗試150或200.對於大多數人來說,每秒更新速度可能足夠快,尤其是因爲它主要是文本。你能在100ms內讀出多少文字?

  5. 如果您仍然遇到比UI線程更新更多的問題,那麼您可能需要使用與pubsub和wx.CallAfter不同的方法。例如,您可以讓工作線程接收並處理數據,然後將對象添加到Queue.Queue,然後調用wx.WakeUpIdle()。在UI線程中,您可以有一個EVT_IDLE事件處理程序,它檢查隊列並將第一個項目從隊列中取出(如果有),然後使用該數據更新小部件。這將帶來好處,即不會用太多wx.CallAfter調用的事件來淹沒待處理事件列表,並且還可以執行諸如從數據隊列中刪除項目(如果項目中項目太多)的操作。

+0

有趣的答案。我對第3點和第5點更感興趣。第3點 - 是不是有更多的代碼可以運行?並減緩進程更多? 第5點:請給我舉個例子。我像一個月前一樣嘗試了隊列,並且失敗的很糟糕,因爲它只給出了一個長度爲192的numpy數組中的一個元素。如果你能給我一個使用wx.WakeupIdle的例子,我將不勝感激 –