2016-03-08 154 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)) 

我知道这需要一些整理,但它的工作原理。如果任何人有一个更优雅的解决方案随时发布。

相关问题