2016-03-08 3 views
0

Я делаю меню, которое работает на ЖК-экране, питаемом от Raspberry Pi. Я пытаюсь использовать модуль потоковой передачи, чтобы текст на ЖК-дисплее обновлялся до тех пор, пока положение меню не изменится.Цитирование функции до тех пор, пока не будет вызвана другая функция

Меню составлено из списка функций, вызываемых при изменении положения меню. Функция 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

Есть много способов для достижения этой цели, один простой способ это сделать то время как цикла в переменной, а затем установить его False за пределами цикла (например, при вызове 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) 

я попробовать/за исключением обойти начальное выполнение 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)) 

Я знаю, что нуждается в некоторой уборки , но он работает. Если у кого-то есть более элегантное решение, не стесняйтесь публиковать его.

Смежные вопросы