Запуск диалогового окна в отдельном потоке и управление им по таймеру на python

Программа работает на одноплатнике Raspberry, на python. Мониторит состояние пина. Если на пине появился сигнал, открывается диалоговое окно и ждем реакции пользователя. Параллельно нужно продолжать мониторить тот же пин. Если в течение 3 секунд на нем вновь появился сигнал, то все ок, продолжаем ждать реакции пользователя (он может нажимать кнопки в диалоге, что вызывает другие окна и т.п.). Если же в течение 3 сек сигнал на пин не поступил, диалог (и все прочие открытые окна) надо зарыть. Далее ждем опять сигнал, показываем диалог, мониторим пин и т.п. Т.е. диалог работает при условии, что не реже раз в 3 сек на пин поступает сигнал.

Как я понимаю, тут нужен таймер на 3 сек, который запускается в отдельном потоке. Таймер нужно обнулять, если пин изменил состояние и снова засекать 3 сек. Если 3 сек прошли, вызывать колбэк, который будет делать Gtk.main_quit(). Как-то так. Но это по сути моя вторая программа на питоне )). Т.е. я с потоками не очень (мягко говоря).

import gi
import RPi.GPIO as GPIO
from threading import Thread, Timer

def gui_close():
   print('Убираем GUI')
   Gtk.main_quit()
 
def gui_open()
   print('Открываем GUI')
   dialog = GtkDialog()
   dialog.show_all()
   Gtk.main()

tmr = Timer(3, gui_close)
def signal_detected():      
   #здесь нужно обнулить (запустить заново) таймер
   #и запустить поток с GUI,
   #если он еще не запущен      

GPIO.setmode(GPIO.BCM)
SIGNAL_PIN = 12
GPIO.setup(SIGNAL_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(SIGNAL_PIN, GPIO.FALLING, callback=signal_detected)

Пожалуйста, знающие люди, помогите разобраться с потоками ).


Ответы (1 шт):

Автор решения: eri

GTK не работает в потоках. Маин обычно запускается на все время работы программы и не закрывается до выхода. Показ окна осуществляется через show, скрывается через hide. Нет особой нужды создавать новые окна.

Ваш код переносится в поток. Взаимодействие с GUI же строится только через вызов gobject.idle_add

Таймер встраивайте в окно и запускайте вместе с show. Хотя лучше его убрать и использовать GObject.timeout_add

→ Ссылка