2016-03-08 92 views
0

我正在製作一個菜單,該菜單在由Raspberry Pi供電的液晶顯示屏上運行。我正在嘗試使用線程模塊使LCD上的文本更新,直到菜單位置改變。循環一個函數,直到調用另一個函數

該菜單由當菜單位置改變時調用的函數列表組成。 switch_menu()函數使用事件處理函數從類外部調用,並用於調用正確的菜單函數。通過其中一些功能(item2);我想讓他們循環,並與他人(item1);只顯示靜態文本。重要的是,當再次調用switch_menu()時,它們會停止循環。我怎樣才能做到這一點?

(這裏是我的代碼的簡化版本)

class Menu: 
    def __init__(self): 
     self.LCD = Adafruit_CharLCD() 

     self.m_pos = 0  

     self.items = [self.item1,self.item2] 

     self.switch_menu(0) 

    def switch_menu(self,operation): 
     # 2. And here I want to stop it. 
     m_pos = self.m_pos 

     pos = m_pos 
     max_pos = len(self.items) - 1 
     m_pos = self.loop_selection(pos,max_pos,operation) 

     # 1. Here I want to start looping the function below. 
     self.items[m_pos]() 

     self.m_pos = m_pos 

    def loop_selection(self,pos,max_pos,operation): 
     if pos >= max_pos and operation == 1: 
      pos = 0 
     elif pos <= 0 and operation == -1: 
      pos = max_pos 
     else: 
      pos += operation 
     return pos 

    def item1(self): 
     self.LCD.clear() 
     text = "item1" 
     self.LCD.message(text) 

    def item2(self): 
     while True: 
      self.LCD.clear() 
      text = "item2" 
      self.LCD.message(text) 
      time.sleep(10) 

回答

0

有很多種方法來實現這一目標,一個簡單的方法是使一個變量循環,然後將其設置爲錯誤一旦你想停止它的循環外(例如,當調用switch_menu時)。只要注意可能導致的任何競爭條件,其中我不能說更多的關於,因爲我不知道你的其他代碼。

+0

感謝您的快速回復。然而,我想到了這一點,如果功能在菜單改變時正在休眠,該計劃似乎沒有反應。我也不確定在哪裏放置多線程代碼以及我應該如何使用它。 –

+0

不直接關於你的問題,你可以考慮的一件小事是_loop_selection_嘗試利用'pos =(pos + 1)%(max_pos + 1)'。 –

+0

關於多線程問題,每個事件觸發一個新線程將調用_switch_menu_? –

0

典型的,我一直試圖讓這個工作幾天,一旦我發佈一個問題;我找到了答案。

這裏就是我發現我的答案是: Stopping a thread after a certain amount of time

這是我做過什麼,使其工作:

class Menu: 
    def __init__(self): 
     self.LCD = Adafruit_CharLCD() 

     self.m_pos = 0  

     self.items = [self.item1,self.item2] 

     self.switch_menu(0) 

    def switch_menu(self,operation): 
     try: 
      self.t_stop.set() 
     except: 
      pass 

     m_pos = self.m_pos 

     pos = m_pos 
     max_pos = len(self.items) - 1 
     m_pos = self.loop_selection(pos,max_pos,operation) 

     item = self.items[m_pos][0] 
     self.t_stop = threading.Event() 
     self.t = threading.Thread(target=item,args=(1,self.t_stop)) 
     self.t.start() 

     self.m_pos = m_pos 

    def loop_selection(self,pos,max_pos,operation): 
     if pos >= max_pos and operation == 1: 
      pos = 0 
     elif pos <= 0 and operation == -1: 
      pos = max_pos 
     else: 
      pos += operation 
     return pos 

    def item1(self,arg): 
     while not stop_event.is_set(): 
      text = "item1" 
      self.LCD.clear() 
      if not stop_event.is_set(): self.LCD.message(text) 
      stop_event.wait(10) 

    def item2(self,arg): 
     while not stop_event.is_set(): 
      text = "item2" 
      self.LCD.clear() 
      if not stop_event.is_set(): self.LCD.message(text) 
      stop_event.wait(10) 

我用一個try /除了繞過switch_menu的初始執行( ):

try: 
    self.t_stop.set() 
except: 
    pass 

我檢查條件的第二時間作爲一種解決方法,以防止競爭條件:

if not stop_event.is_set(): self.LCD.message(text) 

而且我不知道爲什麼我不得不創建一個線程時的參數傳遞,但它給了我,當我沒有錯誤:

self.t = threading.Thread(target=item,args=(1,self.t_stop)) 

我知道這需要一些整理,但它的工作原理。如果任何人有一個更優雅的解決方案隨時發佈。

相關問題