Уведомления

Группа в Telegram: @pythonsu

#1 Июль 5, 2013 16:34:52

buddha
От:
Зарегистрирован: 2012-03-02
Сообщения: 422
Репутация: +  15  -
Профиль   Отправить e-mail  

Не отлавливается нажатие клавиши при запущенном втором потоке. Tkinter\threading.

Вот сценарий:

import threading
import time
from tkinter import Tk
from tkinter import Label
 
TIMEOUT = 10  # Время в секундах, по истечении которго будет посылаться запрос на получение данных.
 
# Функция, которая будет обновлять данные.
def waiter(func):
    while True:
        time.sleep(TIMEOUT)
        func()
 
def main():
    root_widg = Tk()
    root_widg.title('Уведомление по неотвеченным вопросам')
    root_widg.geometry("{}x{}+0+0".format(root_widg.winfo_screenwidth(), root_widg.winfo_screenheight()))
    root_widg.attributes('-fullscreen', 1)
  
    label = Label(root_widg, justify='left', wraplength=root_widg.winfo_screenwidth() - 20)
    label.pack(expand='yes', fill='both')
 
    def output():
    # тут делаю запрос на сервер
    # получаю ответ
    # паршу ответ
    # и в зависимости от пришедших параметров конфигурирую label
    # например label.config(text="Успех", bg='#78207E', fg='#4FEDEE', font=('times', 20, 'bold')) 
  
    thread = threading.Thread(target=waiter, args=(output,))
    thread.start()
 
    def escape(event):
        root_widg.quit()
 
    def leave(event):
        root_widg.attributes('-fullscreen', 0)
 
    def enter(event):
        root_widg.attributes('-fullscreen', 1)
 
    root_widg.bind('<Escape>', escape)
    root_widg.bind('<Alt-F4>', escape)
    root_widg.bind('<FocusIn>', enter)
    root_widg.bind('<FocusOut>', leave)
 
    output()
    root_widg.mainloop()
 
 
if __name__ == '__main__':
    main()

Так вот когда запускаю, ни <Escape>, ни <Alt-F4> не срабатывают для главного окна.
Программа работает, но выход можно сделать только убив процесс в диспетчере.
Помогите оживить закрытие главного окна по нажатию клавиш.

Отредактировано buddha (Июль 5, 2013 17:23:11)

Офлайн

#2 Июль 5, 2013 16:41:50

4kpt
От: Харьков
Зарегистрирован: 2010-11-03
Сообщения: 998
Репутация: +  63  -
Профиль   Отправить e-mail  

Не отлавливается нажатие клавиши при запущенном втором потоке. Tkinter\threading.

Не уверен, что threading будет дружить с tkinter. У tkinter существуют свои механизмы запуска дополнительного цикла обработки событий.

P.S. Никогда не испытывал связку threading и tkinter. Может кто пробовал, тот напишет более внятный ответ или механизм борьбы с Вашей проблемой.



Офлайн

#3 Июль 5, 2013 16:54:57

buddha
От:
Зарегистрирован: 2012-03-02
Сообщения: 422
Репутация: +  15  -
Профиль   Отправить e-mail  

Не отлавливается нажатие клавиши при запущенном втором потоке. Tkinter\threading.

Какой механизм? Через него можно через каждые 10 секунд запускать функцию output(), при этом чтобы отлавливание клавиш не отвалилось?

Офлайн

#4 Июль 5, 2013 17:07:34

4kpt
От: Харьков
Зарегистрирован: 2010-11-03
Сообщения: 998
Репутация: +  63  -
Профиль   Отправить e-mail  

Не отлавливается нажатие клавиши при запущенном втором потоке. Tkinter\threading.

Такие задачи себе не ставил. По-идее можно.
Сейчас попробую и отпишусь.



Отредактировано 4kpt (Июль 5, 2013 17:11:23)

Офлайн

#5 Июль 5, 2013 18:37:39

4kpt
От: Харьков
Зарегистрирован: 2010-11-03
Сообщения: 998
Репутация: +  63  -
Профиль   Отправить e-mail  

Не отлавливается нажатие клавиши при запущенном втором потоке. Tkinter\threading.

Получилось. Ну и задачка…

P.S. Вопрос еще актуален?



Отредактировано 4kpt (Июль 5, 2013 19:05:58)

Офлайн

#6 Июль 5, 2013 23:20:54

buddha
От:
Зарегистрирован: 2012-03-02
Сообщения: 422
Репутация: +  15  -
Профиль   Отправить e-mail  

Не отлавливается нажатие клавиши при запущенном втором потоке. Tkinter\threading.

да, актуально.

4kpt
Ну и задачка…
Пришлось поколдлвать? какие сложности? Я так просто тупо не знаю, почему так себя ведёт програмка.
Без потока всё работает, как часы. Просто необходимо обновление данных… Посему запилен поток.

Офлайн

#7 Июль 6, 2013 00:10:45

4kpt
От: Харьков
Зарегистрирован: 2010-11-03
Сообщения: 998
Репутация: +  63  -
Профиль   Отправить e-mail  

Не отлавливается нажатие клавиши при запущенном втором потоке. Tkinter\threading.

Будете смеяться. Все прозаично и просто. Никаких костылей :)
Ловите…

# -*- coding: utf-8 -*-
import Tkinter
import time
tm = time.time()
def call_passive(event):
    print u"Выполнен шаг процесса."
    # Будет запускаться 10 секунд через каждую секунду
    if time.time() - tm < 10:
        root.after(1000, call_passive, event)
def call_active(event):
    print u"Пассивное нажатие в процессе."
root = Tkinter.Tk()
root.geometry("400x400+100+100")
bt_free = Tkinter.Button(root, width=20, text="Свободно нажимаем")
bt_free.place(relx=0.5, rely=0.33, anchor="center")
bt_free.bind("<ButtonRelease-1>", call_active)
bt_proc = Tkinter.Button(root, width=20, text=u"Запускаем процесс")
bt_proc.place(relx=0.5, rely=0.66, anchor="center")
bt_proc.bind("<ButtonRelease-1>", call_passive)
root.mainloop()
Ну как?



Отредактировано 4kpt (Июль 6, 2013 00:13:35)

Офлайн

#8 Июль 6, 2013 10:40:35

buddha
От:
Зарегистрирован: 2012-03-02
Сообщения: 422
Репутация: +  15  -
Профиль   Отправить e-mail  

Не отлавливается нажатие клавиши при запущенном втором потоке. Tkinter\threading.

Ага вижу, рекусия в методе after(). В гугле видел её, но не пробовал. Попробую поменять реализацию сценария. Отпишусь потом…

Офлайн

#9 Июль 6, 2013 10:46:01

4kpt
От: Харьков
Зарегистрирован: 2010-11-03
Сообщения: 998
Репутация: +  63  -
Профиль   Отправить e-mail  

Не отлавливается нажатие клавиши при запущенном втором потоке. Tkinter\threading.

По гуглю не искал, не знаю, но метод .after() в tkinter запускает параллельный поток событий. О нем я писал выше. Но при его применении с циклом происходило выполнение всех событий одновременно. Если же использовался модуль time, то имело место зависание основного потока. Оставалось только одно - рекурсия, чтобы не ваять цикл, который этот поток событий будет стопарить. В этом случае .after вызывает функцию, котора вызывает в отдельном потоке .after и так циклично. Получается все “по-феншую” :)



Отредактировано 4kpt (Июль 6, 2013 10:50:02)

Офлайн

#10 Июль 8, 2013 08:49:13

buddha
От:
Зарегистрирован: 2012-03-02
Сообщения: 422
Репутация: +  15  -
Профиль   Отправить e-mail  

Не отлавливается нажатие клавиши при запущенном втором потоке. Tkinter\threading.

Ну, а что будет когда рекурсия достигнет своего предела?

>>> sys.getrecursionlimit()
1000

Надо , чтобы сценарий висел долго\постоянно.
Да и я так понял метод after() крайне похож на threading.Timer(). Т.е. проблема отлова нажатия клавиш клавиатуры остаётся…

Отредактировано buddha (Июль 8, 2013 08:51:16)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version